1"use strict"; 2(self["webpackChunkblk_design_system_angular"] = self["webpackChunkblk_design_system_angular"] || []).push([["vendor"],{ 3 4/***/ 4505: 5/*!****************************************************************!*\ 6 !*** ./node_modules/rxjs/_esm2015/internal/BehaviorSubject.js ***! 7 \****************************************************************/ 8/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 9 10__webpack_require__.r(__webpack_exports__); 11/* harmony export */ __webpack_require__.d(__webpack_exports__, { 12/* harmony export */ "BehaviorSubject": () => (/* binding */ BehaviorSubject) 13/* harmony export */ }); 14/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Subject */ 2218); 15/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util/ObjectUnsubscribedError */ 9086); 16 17 18class BehaviorSubject extends _Subject__WEBPACK_IMPORTED_MODULE_0__.Subject { 19 constructor(_value) { 20 super(); 21 this._value = _value; 22 } 23 24 get value() { 25 return this.getValue(); 26 } 27 28 _subscribe(subscriber) { 29 const subscription = super._subscribe(subscriber); 30 31 if (subscription && !subscription.closed) { 32 subscriber.next(this._value); 33 } 34 35 return subscription; 36 } 37 38 getValue() { 39 if (this.hasError) { 40 throw this.thrownError; 41 } else if (this.closed) { 42 throw new _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_1__.ObjectUnsubscribedError(); 43 } else { 44 return this._value; 45 } 46 } 47 48 next(value) { 49 super.next(this._value = value); 50 } 51 52} 53 54/***/ }), 55 56/***/ 472: 57/*!****************************************************************!*\ 58 !*** ./node_modules/rxjs/_esm2015/internal/InnerSubscriber.js ***! 59 \****************************************************************/ 60/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 61 62__webpack_require__.r(__webpack_exports__); 63/* harmony export */ __webpack_require__.d(__webpack_exports__, { 64/* harmony export */ "InnerSubscriber": () => (/* binding */ InnerSubscriber) 65/* harmony export */ }); 66/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Subscriber */ 14); 67 68class InnerSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 69 constructor(parent, outerValue, outerIndex) { 70 super(); 71 this.parent = parent; 72 this.outerValue = outerValue; 73 this.outerIndex = outerIndex; 74 this.index = 0; 75 } 76 77 _next(value) { 78 this.parent.notifyNext(this.outerValue, value, this.outerIndex, this.index++, this); 79 } 80 81 _error(error) { 82 this.parent.notifyError(error, this); 83 this.unsubscribe(); 84 } 85 86 _complete() { 87 this.parent.notifyComplete(this); 88 this.unsubscribe(); 89 } 90 91} 92 93/***/ }), 94 95/***/ 2378: 96/*!***********************************************************!*\ 97 !*** ./node_modules/rxjs/_esm2015/internal/Observable.js ***! 98 \***********************************************************/ 99/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 100 101__webpack_require__.r(__webpack_exports__); 102/* harmony export */ __webpack_require__.d(__webpack_exports__, { 103/* harmony export */ "Observable": () => (/* binding */ Observable) 104/* harmony export */ }); 105/* harmony import */ var _util_canReportError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util/canReportError */ 5739); 106/* harmony import */ var _util_toSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./util/toSubscriber */ 8333); 107/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./symbol/observable */ 6831); 108/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./util/pipe */ 6800); 109/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./config */ 146); 110 111 112 113 114 115class Observable { 116 constructor(subscribe) { 117 this._isScalar = false; 118 119 if (subscribe) { 120 this._subscribe = subscribe; 121 } 122 } 123 124 lift(operator) { 125 const observable = new Observable(); 126 observable.source = this; 127 observable.operator = operator; 128 return observable; 129 } 130 131 subscribe(observerOrNext, error, complete) { 132 const { 133 operator
134 } = this; 135 const sink = (0,_util_toSubscriber__WEBPACK_IMPORTED_MODULE_0__.toSubscriber)(observerOrNext, error, complete); 136 137 if (operator) { 138 sink.add(operator.call(sink, this.source)); 139 } else { 140 sink.add(this.source || _config__WEBPACK_IMPORTED_MODULE_1__.config.useDeprecatedSynchronousErrorHandling && !sink.syncErrorThrowable ? this._subscribe(sink) : this._trySubscribe(sink)); 141 } 142 143 if (_config__WEBPACK_IMPORTED_MODULE_1__.config.useDeprecatedSynchronousErrorHandling) { 144 if (sink.syncErrorThrowable) { 145 sink.syncErrorThrowable = false; 146 147 if (sink.syncErrorThrown) { 148 throw sink.syncErrorValue; 149 } 150 } 151 } 152 153 return sink; 154 } 155 156 _trySubscribe(sink) { 157 try { 158 return this._subscribe(sink); 159 } catch (err) { 160 if (_config__WEBPACK_IMPORTED_MODULE_1__.config.useDeprecatedSynchronousErrorHandling) { 161 sink.syncErrorThrown = true; 162 sink.syncErrorValue = err; 163 } 164 165 if ((0,_util_canReportError__WEBPACK_IMPORTED_MODULE_2__.canReportError)(sink)) { 166 sink.error(err); 167 } else { 168 console.warn(err); 169 } 170 } 171 } 172 173 forEach(next, promiseCtor) { 174 promiseCtor = getPromiseCtor(promiseCtor); 175 return new promiseCtor((resolve, reject) => { 176 let subscription; 177 subscription = this.subscribe(value => { 178 try { 179 next(value); 180 } catch (err) { 181 reject(err); 182 183 if (subscription) { 184 subscription.unsubscribe(); 185 } 186 } 187 }, reject, resolve); 188 }); 189 } 190 191 _subscribe(subscriber) { 192 const { 193 source 194 } = this; 195 return source && source.subscribe(subscriber); 196 } 197 198 [_symbol_observable__WEBPACK_IMPORTED_MODULE_3__.observable]() { 199 return this; 200 } 201 202 pipe(...operations) { 203 if (operations.length === 0) { 204 return this; 205 } 206 207 return (0,_util_pipe__WEBPACK_IMPORTED_MODULE_4__.pipeFromArray)(operations)(this); 208 } 209 210 toPromise(promiseCtor) { 211 promiseCtor = getPromiseCtor(promiseCtor); 212 return new promiseCtor((resolve, reject) => { 213 let value; 214 this.subscribe(x => value = x, err => reject(err), () => resolve(value)); 215 }); 216 } 217 218} 219 220Observable.create = subscribe => { 221 return new Observable(subscribe); 222}; 223 224function getPromiseCtor(promiseCtor) { 225 if (!promiseCtor) { 226 promiseCtor = _config__WEBPACK_IMPORTED_MODULE_1__.config.Promise || Promise; 227 } 228 229 if (!promiseCtor) { 230 throw new Error('no Promise impl found'); 231 } 232 233 return promiseCtor; 234} 235
236/***/ }), 237 238/***/ 9957: 239/*!*********************************************************!*\ 240 !*** ./node_modules/rxjs/_esm2015/internal/Observer.js ***! 241 \*********************************************************/ 242/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 243 244__webpack_require__.r(__webpack_exports__); 245/* harmony export */ __webpack_require__.d(__webpack_exports__, { 246/* harmony export */ "empty": () => (/* binding */ empty) 247/* harmony export */ }); 248/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./config */ 146); 249/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util/hostReportError */ 8897); 250 251 252const empty = { 253 closed: true, 254 255 next(value) {}, 256 257 error(err) { 258 if (_config__WEBPACK_IMPORTED_MODULE_0__.config.useDeprecatedSynchronousErrorHandling) { 259 throw err; 260 } else { 261 (0,_util_hostReportError__WEBPACK_IMPORTED_MODULE_1__.hostReportError)(err); 262 } 263 }, 264 265 complete() {} 266 267}; 268 269/***/ }), 270 271/***/ 5266: 272/*!****************************************************************!*\ 273 !*** ./node_modules/rxjs/_esm2015/internal/OuterSubscriber.js ***! 274 \****************************************************************/ 275/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 276 277__webpack_require__.r(__webpack_exports__); 278/* harmony export */ __webpack_require__.d(__webpack_exports__, { 279/* harmony export */ "OuterSubscriber": () => (/* binding */ OuterSubscriber) 280/* harmony export */ }); 281/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Subscriber */ 14); 282 283class OuterSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 284 notifyNext(outerValue, innerValue, outerIndex, innerIndex, innerSub) { 285 this.destination.next(innerValue); 286 } 287 288 notifyError(error, innerSub) { 289 this.destination.error(error); 290 } 291 292 notifyComplete(innerSub) { 293 this.destination.complete(); 294 } 295 296} 297 298/***/ }), 299 300/***/ 2218: 301/*!********************************************************!*\ 302 !*** ./node_modules/rxjs/_esm2015/internal/Subject.js ***! 303 \********************************************************/ 304/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 305 306__webpack_require__.r(__webpack_exports__); 307/* harmony export */ __webpack_require__.d(__webpack_exports__, { 308/* harmony export */ "AnonymousSubject": () => (/* binding */ AnonymousSubject), 309/* harmony export */ "Subject": () => (/* binding */ Subject), 310/* harmony export */ "SubjectSubscriber": () => (/* binding */ SubjectSubscriber) 311/* harmony export */ }); 312/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Observable */ 2378); 313/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Subscriber */ 14); 314/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Subscription */ 2425); 315/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./util/ObjectUnsubscribedError */ 9086); 316/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./SubjectSubscription */ 1722); 317/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../internal/symbol/rxSubscriber */ 1482); 318 319 320 321 322 323 324class SubjectSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 325 constructor(destination) { 326 super(destination); 327 this.destination = destination; 328 } 329 330} 331class Subject extends _Observable__WEBPACK_IMPORTED_MODULE_1__.Observable { 332 constructor() { 333 super(); 334 this.observers = []; 335 this.closed = false; 336 this.isStopped = false; 337 this.hasError = false; 338 this.thrownError = null; 339 } 340 341 [_internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_2__.rxSubscriber]() { 342 return new SubjectSubscriber(this); 343 } 344 345 lift(operator) { 346 const subject = new AnonymousSubject(this, this); 347 subject.operator = operator; 348 return subject; 349 } 350 351 next(value) { 352 if (this.closed) { 353 throw new _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_3__.ObjectUnsubscribedError(); 354 } 355 356 if (!this.isStopped) { 357 const { 358 observers 359 } = this; 360 const len = observers.length; 361 const copy = observers.slice(); 362 363 for (let i = 0; i < len; i++) { 364 copy[i].next(value); 365 } 366 } 367 } 368 369 error(err) { 370 if (this.closed) { 371 throw new _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_3__.ObjectUnsubscribedError(); 372 } 373 374 this.hasError = true; 375 this.thrownError = err; 376 this.isStopped = true; 377 const { 378 observers 379 } = this; 380 const len = observers.length; 381 const copy = observers.slice(); 382 383 for (let i = 0; i < len; i++) { 384 copy[i].error(err); 385 } 386 387 this.observers.length = 0; 388 } 389 390 complete() { 391 if (this.closed) { 392 throw new _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_3__.ObjectUnsubscribedError(); 393 } 394 395 this.isStopped = true; 396 const { 397 observers 398 } = this; 399 const len = observers.length; 400 const copy = observers.slice(); 401 402 for (let i = 0; i < len; i++) { 403 copy[i].complete(); 404 } 405 406 this.observers.length = 0; 407 } 408 409 unsubscribe() { 410 this.isStopped = true; 411 this.closed = true; 412 this.observers = null; 413 } 414 415 _trySubscribe(subscriber) { 416 if (this.closed) { 417 throw new _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_3__.ObjectUnsubscribedError(); 418 } else { 419 return super._trySubscribe(subscriber); 420 } 421 } 422 423 _subscribe(subscriber) { 424 if (this.closed) { 425 throw new _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_3__.ObjectUnsubscribedError(); 426 } else if (this.hasError) { 427 subscriber.error(this.thrownError); 428 return _Subscription__WEBPACK_IMPORTED_MODULE_4__.Subscription.EMPTY; 429 } else if (this.isStopped) { 430 subscriber.complete(); 431 return _Subscription__WEBPACK_IMPORTED_MODULE_4__.Subscription.EMPTY; 432 } else { 433 this.observers.push(subscriber); 434 return new _SubjectSubscription__WEBPACK_IMPORTED_MODULE_5__.SubjectSubscription(this, subscriber); 435 } 436 } 437 438 asObservable() { 439 const observable = new _Observable__WEBPACK_IMPORTED_MODULE_1__.Observable(); 440 observable.source = this; 441 return observable; 442 } 443 444} 445 446Subject.create = (destination, source) => { 447 return new AnonymousSubject(destination, source); 448}; 449 450class AnonymousSubject extends Subject { 451 constructor(destination, source) { 452 super(); 453 this.destination = destination; 454 this.source = source; 455 } 456 457 next(value) { 458 const { 459 destination 460 } = this; 461 462 if (destination && destination.next) { 463 destination.next(value); 464 } 465 } 466 467 error(err) { 468 const { 469 destination 470 } = this; 471 472 if (destination && destination.error) { 473 this.destination.error(err); 474 } 475 } 476 477 complete() { 478 const { 479 destination 480 } = this; 481 482 if (destination && destination.complete) { 483 this.destination.complete(); 484 } 485 } 486 487 _subscribe(subscriber) { 488 const { 489 source 490 } = this; 491 492 if (source) { 493 return this.source.subscribe(subscriber); 494 } else { 495 return _Subscription__WEBPACK_IMPORTED_MODULE_4__.Subscription.EMPTY; 496 } 497 } 498 499} 500 501/***/ }), 502 503/***/ 1722: 504/*!********************************************************************!*\ 505 !*** ./node_modules/rxjs/_esm2015/internal/SubjectSubscription.js ***! 506 \********************************************************************/ 507/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 508 509__webpack_require__.r(__webpack_exports__); 510/* harmony export */ __webpack_require__.d(__webpack_exports__, { 511/* harmony export */ "SubjectSubscription": () => (/* binding */ SubjectSubscription) 512/* harmony export */ }); 513/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Subscription */ 2425); 514 515class SubjectSubscription extends _Subscription__WEBPACK_IMPORTED_MODULE_0__.Subscription { 516 constructor(subject, subscriber) { 517 super(); 518 this.subject = subject; 519 this.subscriber = subscriber; 520 this.closed = false;
vendor: 4,328 bytes, lines 521-682
521 } 522 523 unsubscribe() { 524 if (this.closed) { 525 return; 526 } 527 528 this.closed = true; 529 const subject = this.subject; 530 const observers = subject.observers; 531 this.subject = null; 532 533 if (!observers || observers.length === 0 || subject.isStopped || subject.closed) { 534 return; 535 } 536 537 const subscriberIndex = observers.indexOf(this.subscriber); 538 539 if (subscriberIndex !== -1) { 540 observers.splice(subscriberIndex, 1); 541 } 542 } 543 544} 545 546/***/ }), 547 548/***/ 14: 549/*!***********************************************************!*\ 550 !*** ./node_modules/rxjs/_esm2015/internal/Subscriber.js ***! 551 \***********************************************************/ 552/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 553 554__webpack_require__.r(__webpack_exports__); 555/* harmony export */ __webpack_require__.d(__webpack_exports__, { 556/* harmony export */ "SafeSubscriber": () => (/* binding */ SafeSubscriber), 557/* harmony export */ "Subscriber": () => (/* binding */ Subscriber) 558/* harmony export */ }); 559/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./util/isFunction */ 1900); 560/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Observer */ 9957); 561/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Subscription */ 2425); 562/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../internal/symbol/rxSubscriber */ 1482); 563/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./config */ 146); 564/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./util/hostReportError */ 8897); 565 566 567 568 569 570 571class Subscriber extends _Subscription__WEBPACK_IMPORTED_MODULE_0__.Subscription { 572 constructor(destinationOrNext, error, complete) { 573 super(); 574 this.syncErrorValue = null; 575 this.syncErrorThrown = false; 576 this.syncErrorThrowable = false; 577 this.isStopped = false; 578 579 switch (arguments.length) { 580 case 0: 581 this.destination = _Observer__WEBPACK_IMPORTED_MODULE_1__.empty; 582 break; 583 584 case 1: 585 if (!destinationOrNext) { 586 this.destination = _Observer__WEBPACK_IMPORTED_MODULE_1__.empty; 587 break; 588 } 589 590 if (typeof destinationOrNext === 'object') { 591 if (destinationOrNext instanceof Subscriber) { 592 this.syncErrorThrowable = destinationOrNext.syncErrorThrowable; 593 this.destination = destinationOrNext; 594 destinationOrNext.add(this); 595 } else { 596 this.syncErrorThrowable = true; 597 this.destination = new SafeSubscriber(this, destinationOrNext); 598 } 599 600 break; 601 } 602 603 default: 604 this.syncErrorThrowable = true; 605 this.destination = new SafeSubscriber(this, destinationOrNext, error, complete); 606 break; 607 } 608 } 609 610 [_internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_2__.rxSubscriber]() { 611 return this; 612 } 613 614 static create(next, error, complete) { 615 const subscriber = new Subscriber(next, error, complete); 616 subscriber.syncErrorThrowable = false; 617 return subscriber; 618 } 619 620 next(value) { 621 if (!this.isStopped) { 622 this._next(value); 623 } 624 } 625 626 error(err) { 627 if (!this.isStopped) { 628 this.isStopped = true; 629 630 this._error(err); 631 } 632 } 633 634 complete() { 635 if (!this.isStopped) { 636 this.isStopped = true; 637 638 this._complete(); 639 } 640 } 641 642 unsubscribe() { 643 if (this.closed) { 644 return; 645 } 646 647 this.isStopped = true; 648 super.unsubscribe(); 649 } 650 651 _next(value) { 652 this.destination.next(value); 653 } 654 655 _error(err) { 656 this.destination.error(err); 657 this.unsubscribe(); 658 } 659 660 _complete() { 661 this.destination.complete(); 662 this.unsubscribe(); 663 } 664 665 _unsubscribeAndRecycle() { 666 const { 667 _parentOrParents 668 } = this; 669 this._parentOrParents = null; 670 this.unsubscribe(); 671 this.closed = false; 672 this.isStopped = false; 673 this._parentOrParents = _parentOrParents; 674 return this; 675 } 676 677} 678class SafeSubscriber extends Subscriber { 679 constructor(_parentSubscriber, observerOrNext, error, complete) { 680 super(); 681 this._parentSubscriber = _parentSubscriber; 682 let next;
683 let context = this; 684 685 if ((0,_util_isFunction__WEBPACK_IMPORTED_MODULE_3__.isFunction)(observerOrNext)) { 686 next = observerOrNext; 687 } else if (observerOrNext) { 688 next = observerOrNext.next; 689 error = observerOrNext.error; 690 complete = observerOrNext.complete; 691 692 if (observerOrNext !== _Observer__WEBPACK_IMPORTED_MODULE_1__.empty) { 693 context = Object.create(observerOrNext); 694 695 if ((0,_util_isFunction__WEBPACK_IMPORTED_MODULE_3__.isFunction)(context.unsubscribe)) { 696 this.add(context.unsubscribe.bind(context)); 697 } 698 699 context.unsubscribe = this.unsubscribe.bind(this); 700 } 701 } 702 703 this._context = context; 704 this._next = next; 705 this._error = error; 706 this._complete = complete; 707 } 708 709 next(value) { 710 if (!this.isStopped && this._next) { 711 const { 712 _parentSubscriber 713 } = this; 714 715 if (!_config__WEBPACK_IMPORTED_MODULE_4__.config.useDeprecatedSynchronousErrorHandling || !_parentSubscriber.syncErrorThrowable) { 716 this.__tryOrUnsub(this._next, value); 717 } else if (this.__tryOrSetError(_parentSubscriber, this._next, value)) { 718 this.unsubscribe(); 719 } 720 } 721 } 722 723 error(err) { 724 if (!this.isStopped) { 725 const { 726 _parentSubscriber 727 } = this; 728 const { 729 useDeprecatedSynchronousErrorHandling 730 } = _config__WEBPACK_IMPORTED_MODULE_4__.config; 731 732 if (this._error) { 733 if (!useDeprecatedSynchronousErrorHandling || !_parentSubscriber.syncErrorThrowable) { 734 this.__tryOrUnsub(this._error, err); 735 736 this.unsubscribe(); 737 } else { 738 this.__tryOrSetError(_parentSubscriber, this._error, err); 739 740 this.unsubscribe(); 741 } 742 } else if (!_parentSubscriber.syncErrorThrowable) { 743 this.unsubscribe(); 744 745 if (useDeprecatedSynchronousErrorHandling) { 746 throw err; 747 } 748 749 (0,_util_hostReportError__WEBPACK_IMPORTED_MODULE_5__.hostReportError)(err); 750 } else { 751 if (useDeprecatedSynchronousErrorHandling) { 752 _parentSubscriber.syncErrorValue = err; 753 _parentSubscriber.syncErrorThrown = true; 754 } else { 755 (0,_util_hostReportError__WEBPACK_IMPORTED_MODULE_5__.hostReportError)(err); 756 } 757 758 this.unsubscribe(); 759 } 760 } 761 } 762 763 complete() { 764 if (!this.isStopped) { 765 const { 766 _parentSubscriber 767 } = this; 768 769 if (this._complete) { 770 const wrappedComplete = () => this._complete.call(this._context); 771 772 if (!_config__WEBPACK_IMPORTED_MODULE_4__.config.useDeprecatedSynchronousErrorHandling || !_parentSubscriber.syncErrorThrowable) { 773 this.__tryOrUnsub(wrappedComplete); 774 775 this.unsubscribe(); 776 } else { 777 this.__tryOrSetError(_parentSubscriber, wrappedComplete); 778 779 this.unsubscribe(); 780 } 781 } else { 782 this.unsubscribe(); 783 } 784 } 785 } 786 787 __tryOrUnsub(fn, value) { 788 try { 789 fn.call(this._context, value); 790 } catch (err) { 791 this.unsubscribe(); 792 793 if (_config__WEBPACK_IMPORTED_MODULE_4__.config.useDeprecatedSynchronousErrorHandling) { 794 throw err; 795 } else { 796 (0,_util_hostReportError__WEBPACK_IMPORTED_MODULE_5__.hostReportError)(err); 797 } 798 } 799 } 800 801 __tryOrSetError(parent, fn, value) { 802 if (!_config__WEBPACK_IMPORTED_MODULE_4__.config.useDeprecatedSynchronousErrorHandling) { 803 throw new Error('bad call'); 804 } 805 806 try { 807 fn.call(this._context, value); 808 } catch (err) { 809 if (_config__WEBPACK_IMPORTED_MODULE_4__.config.useDeprecatedSynchronousErrorHandling) { 810 parent.syncErrorValue = err; 811 parent.syncErrorThrown = true; 812 return true; 813 } else { 814 (0,_util_hostReportError__WEBPACK_IMPORTED_MODULE_5__.hostReportError)(err); 815 return true; 816 } 817 } 818 819 return false; 820 } 821 822 _unsubscribe() { 823 const { 824 _parentSubscriber 825 } = this; 826 this._context = null; 827 this._parentSubscriber = null; 828 829 _parentSubscriber.unsubscribe(); 830 } 831 832} 833 834/***/ }), 835 836/***/ 2425: 837/*!*************************************************************!*\ 838 !*** ./node_modules/rxjs/_esm2015/internal/Subscription.js ***! 839 \*************************************************************/ 840/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 841 842__webpack_require__.r(__webpack_exports__); 843/* harmony export */ __webpack_require__.d(__webpack_exports__, { 844/* harmony export */ "Subscription": () => (/* binding */ Subscription) 845/* harmony export */ }); 846/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util/isArray */ 4327); 847/* harmony import */ var _util_isObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./util/isObject */ 6549); 848/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./util/isFunction */ 1900); 849/* harmony import */ var _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util/UnsubscriptionError */ 7875); 850 851 852 853 854class Subscription { 855 constructor(unsubscribe) { 856 this.closed = false;
vendor: 4,639 bytes, lines 857-1027
857 this._parentOrParents = null; 858 this._subscriptions = null; 859 860 if (unsubscribe) { 861 this._ctorUnsubscribe = true; 862 this._unsubscribe = unsubscribe; 863 } 864 } 865 866 unsubscribe() { 867 let errors; 868 869 if (this.closed) { 870 return; 871 } 872 873 let { 874 _parentOrParents, 875 _ctorUnsubscribe, 876 _unsubscribe, 877 _subscriptions 878 } = this; 879 this.closed = true; 880 this._parentOrParents = null; 881 this._subscriptions = null; 882 883 if (_parentOrParents instanceof Subscription) { 884 _parentOrParents.remove(this); 885 } else if (_parentOrParents !== null) { 886 for (let index = 0; index < _parentOrParents.length; ++index) { 887 const parent = _parentOrParents[index]; 888 parent.remove(this); 889 } 890 } 891 892 if ((0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(_unsubscribe)) { 893 if (_ctorUnsubscribe) { 894 this._unsubscribe = undefined; 895 } 896 897 try { 898 _unsubscribe.call(this); 899 } catch (e) { 900 errors = e instanceof _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_1__.UnsubscriptionError ? flattenUnsubscriptionErrors(e.errors) : [e]; 901 } 902 } 903 904 if ((0,_util_isArray__WEBPACK_IMPORTED_MODULE_2__.isArray)(_subscriptions)) { 905 let index = -1; 906 let len = _subscriptions.length; 907 908 while (++index < len) { 909 const sub = _subscriptions[index]; 910 911 if ((0,_util_isObject__WEBPACK_IMPORTED_MODULE_3__.isObject)(sub)) { 912 try { 913 sub.unsubscribe(); 914 } catch (e) { 915 errors = errors || []; 916 917 if (e instanceof _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_1__.UnsubscriptionError) { 918 errors = errors.concat(flattenUnsubscriptionErrors(e.errors)); 919 } else { 920 errors.push(e); 921 } 922 } 923 } 924 } 925 } 926 927 if (errors) { 928 throw new _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_1__.UnsubscriptionError(errors); 929 } 930 } 931 932 add(teardown) { 933 let subscription = teardown; 934 935 if (!teardown) { 936 return Subscription.EMPTY; 937 } 938 939 switch (typeof teardown) { 940 case 'function': 941 subscription = new Subscription(teardown); 942 943 case 'object': 944 if (subscription === this || subscription.closed || typeof subscription.unsubscribe !== 'function') { 945 return subscription; 946 } else if (this.closed) { 947 subscription.unsubscribe(); 948 return subscription; 949 } else if (!(subscription instanceof Subscription)) { 950 const tmp = subscription; 951 subscription = new Subscription(); 952 subscription._subscriptions = [tmp]; 953 } 954 955 break; 956 957 default: 958 { 959 throw new Error('unrecognized teardown ' + teardown + ' added to Subscription.'); 960 } 961 } 962 963 let { 964 _parentOrParents 965 } = subscription; 966 967 if (_parentOrParents === null) { 968 subscription._parentOrParents = this; 969 } else if (_parentOrParents instanceof Subscription) { 970 if (_parentOrParents === this) { 971 return subscription; 972 } 973 974 subscription._parentOrParents = [_parentOrParents, this]; 975 } else if (_parentOrParents.indexOf(this) === -1) { 976 _parentOrParents.push(this); 977 } else { 978 return subscription; 979 } 980 981 const subscriptions = this._subscriptions; 982 983 if (subscriptions === null) { 984 this._subscriptions = [subscription]; 985 } else { 986 subscriptions.push(subscription); 987 } 988 989 return subscription; 990 } 991 992 remove(subscription) { 993 const subscriptions = this._subscriptions; 994 995 if (subscriptions) { 996 const subscriptionIndex = subscriptions.indexOf(subscription); 997 998 if (subscriptionIndex !== -1) { 999 subscriptions.splice(subscriptionIndex, 1); 1000 } 1001 } 1002 } 1003 1004} 1005 1006Subscription.EMPTY = function (empty) { 1007 empty.closed = true; 1008 return empty; 1009}(new Subscription()); 1010 1011function flattenUnsubscriptionErrors(errors) { 1012 return errors.reduce((errs, err) => errs.concat(err instanceof _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_1__.UnsubscriptionError ? err.errors : err), []); 1013} 1014 1015/***/ }), 1016 1017/***/ 146: 1018/*!*******************************************************!*\ 1019 !*** ./node_modules/rxjs/_esm2015/internal/config.js ***! 1020 \*******************************************************/ 1021/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1022 1023__webpack_require__.r(__webpack_exports__); 1024/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1025/* harmony export */ "config": () => (/* binding */ config) 1026/* harmony export */ }); 1027let _enable_super_gross_mode_that_will_cause_bad_things = false;
1028const config = { 1029 Promise: undefined, 1030 1031 set useDeprecatedSynchronousErrorHandling(value) { 1032 if (value) { 1033 const error = new Error(); 1034 console.warn('DEPRECATED! RxJS was set to use deprecated synchronous error handling behavior by code at: \n' + error.stack); 1035 } else if (_enable_super_gross_mode_that_will_cause_bad_things) { 1036 console.log('RxJS: Back to a better error behavior. Thank you. <3'); 1037 } 1038 1039 _enable_super_gross_mode_that_will_cause_bad_things = value; 1040 }, 1041 1042 get useDeprecatedSynchronousErrorHandling() { 1043 return _enable_super_gross_mode_that_will_cause_bad_things; 1044 } 1045 1046}; 1047 1048/***/ }), 1049 1050/***/ 2831: 1051/*!***************************************************************!*\ 1052 !*** ./node_modules/rxjs/_esm2015/internal/innerSubscribe.js ***! 1053 \***************************************************************/ 1054/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1055 1056__webpack_require__.r(__webpack_exports__); 1057/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1058/* harmony export */ "ComplexInnerSubscriber": () => (/* binding */ ComplexInnerSubscriber), 1059/* harmony export */ "ComplexOuterSubscriber": () => (/* binding */ ComplexOuterSubscriber), 1060/* harmony export */ "SimpleInnerSubscriber": () => (/* binding */ SimpleInnerSubscriber), 1061/* harmony export */ "SimpleOuterSubscriber": () => (/* binding */ SimpleOuterSubscriber), 1062/* harmony export */ "innerSubscribe": () => (/* binding */ innerSubscribe) 1063/* harmony export */ }); 1064/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Subscriber */ 14); 1065/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Observable */ 2378); 1066/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util/subscribeTo */ 6983); 1067 1068 1069 1070class SimpleInnerSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 1071 constructor(parent) { 1072 super(); 1073 this.parent = parent; 1074 } 1075 1076 _next(value) { 1077 this.parent.notifyNext(value); 1078 } 1079 1080 _error(error) { 1081 this.parent.notifyError(error); 1082 this.unsubscribe(); 1083 } 1084 1085 _complete() { 1086 this.parent.notifyComplete(); 1087 this.unsubscribe(); 1088 } 1089 1090} 1091class ComplexInnerSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 1092 constructor(parent, outerValue, outerIndex) { 1093 super(); 1094 this.parent = parent; 1095 this.outerValue = outerValue; 1096 this.outerIndex = outerIndex; 1097 } 1098 1099 _next(value) { 1100 this.parent.notifyNext(this.outerValue, value, this.outerIndex, this); 1101 } 1102 1103 _error(error) { 1104 this.parent.notifyError(error); 1105 this.unsubscribe(); 1106 } 1107 1108 _complete() { 1109 this.parent.notifyComplete(this); 1110 this.unsubscribe(); 1111 } 1112 1113} 1114class SimpleOuterSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 1115 notifyNext(innerValue) { 1116 this.destination.next(innerValue); 1117 } 1118 1119 notifyError(err) { 1120 this.destination.error(err); 1121 } 1122 1123 notifyComplete() { 1124 this.destination.complete(); 1125 } 1126 1127} 1128class ComplexOuterSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 1129 notifyNext(_outerValue, innerValue, _outerIndex, _innerSub) { 1130 this.destination.next(innerValue); 1131 } 1132 1133 notifyError(error) { 1134 this.destination.error(error); 1135 } 1136 1137 notifyComplete(_innerSub) { 1138 this.destination.complete(); 1139 } 1140 1141} 1142function innerSubscribe(result, innerSubscriber) { 1143 if (innerSubscriber.closed) { 1144 return undefined; 1145 } 1146 1147 if (result instanceof _Observable__WEBPACK_IMPORTED_MODULE_1__.Observable) { 1148 return result.subscribe(innerSubscriber); 1149 } 1150 1151 return (0,_util_subscribeTo__WEBPACK_IMPORTED_MODULE_2__.subscribeTo)(result)(innerSubscriber); 1152} 1153 1154/***/ }), 1155 1156/***/ 4483: 1157/*!*********************************************************************************!*\ 1158 !*** ./node_modules/rxjs/_esm2015/internal/observable/ConnectableObservable.js ***! 1159 \*********************************************************************************/ 1160/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1161 1162__webpack_require__.r(__webpack_exports__); 1163/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1164/* harmony export */ "ConnectableObservable": () => (/* binding */ ConnectableObservable), 1165/* harmony export */ "connectableObservableDescriptor": () => (/* binding */ connectableObservableDescriptor) 1166/* harmony export */ }); 1167/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Subject */ 2218); 1168/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 2378); 1169/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../Subscriber */ 14); 1170/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Subscription */ 2425); 1171/* harmony import */ var _operators_refCount__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../operators/refCount */ 8331); 1172 1173 1174 1175 1176 1177class ConnectableObservable extends _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable { 1178 constructor(source, subjectFactory) { 1179 super(); 1180 this.source = source; 1181 this.subjectFactory = subjectFactory; 1182 this._refCount = 0; 1183 this._isComplete = false;
vendor: 4,258 bytes, lines 1184-1374
1184 } 1185 1186 _subscribe(subscriber) { 1187 return this.getSubject().subscribe(subscriber); 1188 } 1189 1190 getSubject() { 1191 const subject = this._subject; 1192 1193 if (!subject || subject.isStopped) { 1194 this._subject = this.subjectFactory(); 1195 } 1196 1197 return this._subject; 1198 } 1199 1200 connect() { 1201 let connection = this._connection; 1202 1203 if (!connection) { 1204 this._isComplete = false; 1205 connection = this._connection = new _Subscription__WEBPACK_IMPORTED_MODULE_1__.Subscription(); 1206 connection.add(this.source.subscribe(new ConnectableSubscriber(this.getSubject(), this))); 1207 1208 if (connection.closed) { 1209 this._connection = null; 1210 connection = _Subscription__WEBPACK_IMPORTED_MODULE_1__.Subscription.EMPTY; 1211 } 1212 } 1213 1214 return connection; 1215 } 1216 1217 refCount() { 1218 return (0,_operators_refCount__WEBPACK_IMPORTED_MODULE_2__.refCount)()(this); 1219 } 1220 1221} 1222const connectableObservableDescriptor = (() => { 1223 const connectableProto = ConnectableObservable.prototype; 1224 return { 1225 operator: { 1226 value: null 1227 }, 1228 _refCount: { 1229 value: 0, 1230 writable: true 1231 }, 1232 _subject: { 1233 value: null, 1234 writable: true 1235 }, 1236 _connection: { 1237 value: null, 1238 writable: true 1239 }, 1240 _subscribe: { 1241 value: connectableProto._subscribe 1242 }, 1243 _isComplete: { 1244 value: connectableProto._isComplete, 1245 writable: true 1246 }, 1247 getSubject: { 1248 value: connectableProto.getSubject 1249 }, 1250 connect: { 1251 value: connectableProto.connect 1252 }, 1253 refCount: { 1254 value: connectableProto.refCount 1255 } 1256 }; 1257})(); 1258 1259class ConnectableSubscriber extends _Subject__WEBPACK_IMPORTED_MODULE_3__.SubjectSubscriber { 1260 constructor(destination, connectable) { 1261 super(destination); 1262 this.connectable = connectable; 1263 } 1264 1265 _error(err) { 1266 this._unsubscribe(); 1267 1268 super._error(err); 1269 } 1270 1271 _complete() { 1272 this.connectable._isComplete = true; 1273 1274 this._unsubscribe(); 1275 1276 super._complete(); 1277 } 1278 1279 _unsubscribe() { 1280 const connectable = this.connectable; 1281 1282 if (connectable) { 1283 this.connectable = null; 1284 const connection = connectable._connection; 1285 connectable._refCount = 0; 1286 connectable._subject = null; 1287 connectable._connection = null; 1288 1289 if (connection) { 1290 connection.unsubscribe(); 1291 } 1292 } 1293 } 1294 1295} 1296 1297class RefCountOperator { 1298 constructor(connectable) { 1299 this.connectable = connectable; 1300 } 1301 1302 call(subscriber, source) { 1303 const { 1304 connectable 1305 } = this; 1306 connectable._refCount++; 1307 const refCounter = new RefCountSubscriber(subscriber, connectable); 1308 const subscription = source.subscribe(refCounter); 1309 1310 if (!refCounter.closed) { 1311 refCounter.connection = connectable.connect(); 1312 } 1313 1314 return subscription; 1315 } 1316 1317} 1318 1319class RefCountSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_4__.Subscriber { 1320 constructor(destination, connectable) { 1321 super(destination); 1322 this.connectable = connectable; 1323 } 1324 1325 _unsubscribe() { 1326 const { 1327 connectable 1328 } = this; 1329 1330 if (!connectable) { 1331 this.connection = null; 1332 return; 1333 } 1334 1335 this.connectable = null; 1336 const refCount = connectable._refCount; 1337 1338 if (refCount <= 0) { 1339 this.connection = null; 1340 return; 1341 } 1342 1343 connectable._refCount = refCount - 1; 1344 1345 if (refCount > 1) { 1346 this.connection = null; 1347 return; 1348 } 1349 1350 const { 1351 connection 1352 } = this; 1353 const sharedConnection = connectable._connection; 1354 this.connection = null; 1355 1356 if (sharedConnection && (!connection || sharedConnection === connection)) { 1357 sharedConnection.unsubscribe(); 1358 } 1359 } 1360 1361} 1362 1363/***/ }), 1364 1365/***/ 9193: 1366/*!*************************************************************************!*\ 1367 !*** ./node_modules/rxjs/_esm2015/internal/observable/combineLatest.js ***! 1368 \*************************************************************************/ 1369/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1370 1371__webpack_require__.r(__webpack_exports__); 1372/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1373/* harmony export */ "CombineLatestOperator": () => (/* binding */ CombineLatestOperator), 1374/* harmony export */ "CombineLatestSubscriber": () => (/* binding */ CombineLatestSubscriber),
1375/* harmony export */ "combineLatest": () => (/* binding */ combineLatest) 1376/* harmony export */ }); 1377/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isScheduler */ 7507); 1378/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/isArray */ 4327); 1379/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../OuterSubscriber */ 5266); 1380/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../util/subscribeToResult */ 640); 1381/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./fromArray */ 8005); 1382 1383 1384 1385 1386 1387const NONE = {}; 1388function combineLatest(...observables) { 1389 let resultSelector = undefined; 1390 let scheduler = undefined; 1391 1392 if ((0,_util_isScheduler__WEBPACK_IMPORTED_MODULE_0__.isScheduler)(observables[observables.length - 1])) { 1393 scheduler = observables.pop(); 1394 } 1395 1396 if (typeof observables[observables.length - 1] === 'function') { 1397 resultSelector = observables.pop(); 1398 } 1399 1400 if (observables.length === 1 && (0,_util_isArray__WEBPACK_IMPORTED_MODULE_1__.isArray)(observables[0])) { 1401 observables = observables[0]; 1402 } 1403 1404 return (0,_fromArray__WEBPACK_IMPORTED_MODULE_2__.fromArray)(observables, scheduler).lift(new CombineLatestOperator(resultSelector)); 1405} 1406class CombineLatestOperator { 1407 constructor(resultSelector) { 1408 this.resultSelector = resultSelector; 1409 } 1410 1411 call(subscriber, source) { 1412 return source.subscribe(new CombineLatestSubscriber(subscriber, this.resultSelector)); 1413 } 1414 1415} 1416class CombineLatestSubscriber extends _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__.OuterSubscriber { 1417 constructor(destination, resultSelector) { 1418 super(destination); 1419 this.resultSelector = resultSelector; 1420 this.active = 0; 1421 this.values = []; 1422 this.observables = []; 1423 } 1424 1425 _next(observable) { 1426 this.values.push(NONE); 1427 this.observables.push(observable); 1428 } 1429 1430 _complete() { 1431 const observables = this.observables; 1432 const len = observables.length; 1433 1434 if (len === 0) { 1435 this.destination.complete(); 1436 } else { 1437 this.active = len; 1438 this.toRespond = len; 1439 1440 for (let i = 0; i < len; i++) { 1441 const observable = observables[i]; 1442 this.add((0,_util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__.subscribeToResult)(this, observable, undefined, i)); 1443 } 1444 } 1445 } 1446 1447 notifyComplete(unused) { 1448 if ((this.active -= 1) === 0) { 1449 this.destination.complete(); 1450 } 1451 } 1452 1453 notifyNext(_outerValue, innerValue, outerIndex) { 1454 const values = this.values; 1455 const oldVal = values[outerIndex]; 1456 const toRespond = !this.toRespond ? 0 : oldVal === NONE ? --this.toRespond : this.toRespond; 1457 values[outerIndex] = innerValue; 1458 1459 if (toRespond === 0) { 1460 if (this.resultSelector) { 1461 this._tryResultSelector(values); 1462 } else { 1463 this.destination.next(values.slice()); 1464 } 1465 } 1466 } 1467 1468 _tryResultSelector(values) { 1469 let result; 1470 1471 try { 1472 result = this.resultSelector.apply(this, values); 1473 } catch (err) { 1474 this.destination.error(err); 1475 return; 1476 } 1477 1478 this.destination.next(result); 1479 } 1480 1481} 1482 1483/***/ }), 1484 1485/***/ 5828: 1486/*!******************************************************************!*\ 1487 !*** ./node_modules/rxjs/_esm2015/internal/observable/concat.js ***! 1488 \******************************************************************/ 1489/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1490 1491__webpack_require__.r(__webpack_exports__); 1492/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1493/* harmony export */ "concat": () => (/* binding */ concat) 1494/* harmony export */ }); 1495/* harmony import */ var _of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./of */ 4139); 1496/* harmony import */ var _operators_concatAll__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../operators/concatAll */ 2692); 1497 1498 1499function concat(...observables) { 1500 return (0,_operators_concatAll__WEBPACK_IMPORTED_MODULE_0__.concatAll)()((0,_of__WEBPACK_IMPORTED_MODULE_1__.of)(...observables)); 1501} 1502 1503/***/ }), 1504 1505/***/ 2160: 1506/*!*****************************************************************!*\ 1507 !*** ./node_modules/rxjs/_esm2015/internal/observable/defer.js ***! 1508 \*****************************************************************/ 1509/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1510 1511__webpack_require__.r(__webpack_exports__); 1512/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1513/* harmony export */ "defer": () => (/* binding */ defer) 1514/* harmony export */ }); 1515/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 2378); 1516/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./from */ 4383); 1517/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./empty */ 6439); 1518 1519 1520 1521function defer(observableFactory) { 1522 return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => { 1523 let input; 1524 1525 try { 1526 input = observableFactory(); 1527 } catch (err) { 1528 subscriber.error(err); 1529 return undefined; 1530 } 1531 1532 const source = input ? (0,_from__WEBPACK_IMPORTED_MODULE_1__.from)(input) : (0,_empty__WEBPACK_IMPORTED_MODULE_2__.empty)(); 1533 return source.subscribe(subscriber); 1534 }); 1535} 1536 1537/***/ }), 1538 1539/***/ 6439: 1540/*!*****************************************************************!*\ 1541 !*** ./node_modules/rxjs/_esm2015/internal/observable/empty.js ***! 1542 \*****************************************************************/ 1543/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1544 1545__webpack_require__.r(__webpack_exports__); 1546/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1547/* harmony export */ "EMPTY": () => (/* binding */ EMPTY), 1548/* harmony export */ "empty": () => (/* binding */ empty) 1549/* harmony export */ }); 1550/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 2378); 1551 1552const EMPTY = new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => subscriber.complete()); 1553function empty(scheduler) { 1554 return scheduler ? emptyScheduled(scheduler) : EMPTY; 1555} 1556 1557function emptyScheduled(scheduler) { 1558 return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => scheduler.schedule(() => subscriber.complete())); 1559} 1560 1561/***/ }), 1562 1563/***/ 4350: 1564/*!********************************************************************!*\ 1565 !*** ./node_modules/rxjs/_esm2015/internal/observable/forkJoin.js ***! 1566 \********************************************************************/ 1567/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1568 1569__webpack_require__.r(__webpack_exports__); 1570/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1571/* harmony export */ "forkJoin": () => (/* binding */ forkJoin) 1572/* harmony export */ }); 1573/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Observable */ 2378); 1574/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isArray */ 4327); 1575/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../operators/map */ 6942); 1576/* harmony import */ var _util_isObject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/isObject */ 6549); 1577/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./from */ 4383); 1578 1579 1580 1581 1582 1583function forkJoin(...sources) { 1584 if (sources.length === 1) { 1585 const first = sources[0]; 1586 1587 if ((0,_util_isArray__WEBPACK_IMPORTED_MODULE_0__.isArray)(first)) { 1588 return forkJoinInternal(first, null); 1589 } 1590 1591 if ((0,_util_isObject__WEBPACK_IMPORTED_MODULE_1__.isObject)(first) && Object.getPrototypeOf(first) === Object.prototype) {
1592 const keys = Object.keys(first); 1593 return forkJoinInternal(keys.map(key => first[key]), keys); 1594 } 1595 } 1596 1597 if (typeof sources[sources.length - 1] === 'function') { 1598 const resultSelector = sources.pop(); 1599 sources = sources.length === 1 && (0,_util_isArray__WEBPACK_IMPORTED_MODULE_0__.isArray)(sources[0]) ? sources[0] : sources; 1600 return forkJoinInternal(sources, null).pipe((0,_operators_map__WEBPACK_IMPORTED_MODULE_2__.map)(args => resultSelector(...args))); 1601 } 1602 1603 return forkJoinInternal(sources, null); 1604} 1605 1606function forkJoinInternal(sources, keys) { 1607 return new _Observable__WEBPACK_IMPORTED_MODULE_3__.Observable(subscriber => { 1608 const len = sources.length; 1609 1610 if (len === 0) { 1611 subscriber.complete(); 1612 return; 1613 } 1614 1615 const values = new Array(len); 1616 let completed = 0; 1617 let emitted = 0; 1618 1619 for (let i = 0; i < len; i++) { 1620 const source = (0,_from__WEBPACK_IMPORTED_MODULE_4__.from)(sources[i]); 1621 let hasValue = false; 1622 subscriber.add(source.subscribe({ 1623 next: value => { 1624 if (!hasValue) { 1625 hasValue = true; 1626 emitted++; 1627 } 1628 1629 values[i] = value; 1630 }, 1631 error: err => subscriber.error(err), 1632 complete: () => { 1633 completed++; 1634 1635 if (completed === len || !hasValue) { 1636 if (emitted === len) { 1637 subscriber.next(keys ? keys.reduce((result, key, i) => (result[key] = values[i], result), {}) : values); 1638 } 1639 1640 subscriber.complete(); 1641 } 1642 } 1643 })); 1644 } 1645 }); 1646} 1647 1648/***/ }), 1649 1650/***/ 4383: 1651/*!****************************************************************!*\ 1652 !*** ./node_modules/rxjs/_esm2015/internal/observable/from.js ***! 1653 \****************************************************************/ 1654/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1655 1656__webpack_require__.r(__webpack_exports__); 1657/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1658/* harmony export */ "from": () => (/* binding */ from) 1659/* harmony export */ }); 1660/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 2378); 1661/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/subscribeTo */ 6983); 1662/* harmony import */ var _scheduled_scheduled__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../scheduled/scheduled */ 2476); 1663 1664 1665 1666function from(input, scheduler) { 1667 if (!scheduler) { 1668 if (input instanceof _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable) { 1669 return input; 1670 } 1671 1672 return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable((0,_util_subscribeTo__WEBPACK_IMPORTED_MODULE_1__.subscribeTo)(input)); 1673 } else { 1674 return (0,_scheduled_scheduled__WEBPACK_IMPORTED_MODULE_2__.scheduled)(input, scheduler); 1675 } 1676} 1677 1678/***/ }), 1679 1680/***/ 8005: 1681/*!*********************************************************************!*\ 1682 !*** ./node_modules/rxjs/_esm2015/internal/observable/fromArray.js ***! 1683 \*********************************************************************/ 1684/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1685 1686__webpack_require__.r(__webpack_exports__); 1687/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1688/* harmony export */ "fromArray": () => (/* binding */ fromArray) 1689/* harmony export */ }); 1690/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 2378); 1691/* harmony import */ var _util_subscribeToArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/subscribeToArray */ 5414); 1692/* harmony import */ var _scheduled_scheduleArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../scheduled/scheduleArray */ 8403); 1693 1694 1695 1696function fromArray(input, scheduler) { 1697 if (!scheduler) { 1698 return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable((0,_util_subscribeToArray__WEBPACK_IMPORTED_MODULE_1__.subscribeToArray)(input)); 1699 } else { 1700 return (0,_scheduled_scheduleArray__WEBPACK_IMPORTED_MODULE_2__.scheduleArray)(input, scheduler); 1701 } 1702} 1703 1704/***/ }), 1705 1706/***/ 6312: 1707/*!*********************************************************************!*\ 1708 !*** ./node_modules/rxjs/_esm2015/internal/observable/fromEvent.js ***! 1709 \*********************************************************************/ 1710/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1711 1712__webpack_require__.r(__webpack_exports__); 1713/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1714/* harmony export */ "fromEvent": () => (/* binding */ fromEvent) 1715/* harmony export */ }); 1716/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Observable */ 2378); 1717/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/isArray */ 4327); 1718/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isFunction */ 1900); 1719/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../operators/map */ 6942); 1720 1721 1722 1723 1724 1725const toString = (() => Object.prototype.toString)(); 1726
1727function fromEvent(target, eventName, options, resultSelector) { 1728 if ((0,_util_isFunction__WEBPACK_IMPORTED_MODULE_0__.isFunction)(options)) { 1729 resultSelector = options; 1730 options = undefined; 1731 } 1732 1733 if (resultSelector) { 1734 return fromEvent(target, eventName, options).pipe((0,_operators_map__WEBPACK_IMPORTED_MODULE_1__.map)(args => (0,_util_isArray__WEBPACK_IMPORTED_MODULE_2__.isArray)(args) ? resultSelector(...args) : resultSelector(args))); 1735 } 1736 1737 return new _Observable__WEBPACK_IMPORTED_MODULE_3__.Observable(subscriber => { 1738 function handler(e) { 1739 if (arguments.length > 1) { 1740 subscriber.next(Array.prototype.slice.call(arguments)); 1741 } else { 1742 subscriber.next(e); 1743 } 1744 } 1745 1746 setupSubscription(target, eventName, handler, subscriber, options); 1747 }); 1748} 1749 1750function setupSubscription(sourceObj, eventName, handler, subscriber, options) { 1751 let unsubscribe; 1752 1753 if (isEventTarget(sourceObj)) { 1754 const source = sourceObj; 1755 sourceObj.addEventListener(eventName, handler, options); 1756 1757 unsubscribe = () => source.removeEventListener(eventName, handler, options); 1758 } else if (isJQueryStyleEventEmitter(sourceObj)) { 1759 const source = sourceObj; 1760 sourceObj.on(eventName, handler); 1761 1762 unsubscribe = () => source.off(eventName, handler); 1763 } else if (isNodeStyleEventEmitter(sourceObj)) { 1764 const source = sourceObj; 1765 sourceObj.addListener(eventName, handler); 1766 1767 unsubscribe = () => source.removeListener(eventName, handler); 1768 } else if (sourceObj && sourceObj.length) { 1769 for (let i = 0, len = sourceObj.length; i < len; i++) { 1770 setupSubscription(sourceObj[i], eventName, handler, subscriber, options); 1771 } 1772 } else { 1773 throw new TypeError('Invalid event target'); 1774 } 1775 1776 subscriber.add(unsubscribe); 1777} 1778 1779function isNodeStyleEventEmitter(sourceObj) { 1780 return sourceObj && typeof sourceObj.addListener === 'function' && typeof sourceObj.removeListener === 'function'; 1781} 1782 1783function isJQueryStyleEventEmitter(sourceObj) { 1784 return sourceObj && typeof sourceObj.on === 'function' && typeof sourceObj.off === 'function'; 1785} 1786 1787function isEventTarget(sourceObj) { 1788 return sourceObj && typeof sourceObj.addEventListener === 'function' && typeof sourceObj.removeEventListener === 'function'; 1789} 1790 1791/***/ }), 1792 1793/***/ 8623: 1794/*!*****************************************************************!*\ 1795 !*** ./node_modules/rxjs/_esm2015/internal/observable/merge.js ***! 1796 \*****************************************************************/ 1797/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1798 1799__webpack_require__.r(__webpack_exports__); 1800/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1801/* harmony export */ "merge": () => (/* binding */ merge) 1802/* harmony export */ }); 1803/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Observable */ 2378); 1804/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isScheduler */ 7507); 1805/* harmony import */ var _operators_mergeAll__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../operators/mergeAll */ 6675); 1806/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./fromArray */ 8005); 1807 1808 1809 1810 1811function merge(...observables) { 1812 let concurrent = Number.POSITIVE_INFINITY; 1813 let scheduler = null; 1814 let last = observables[observables.length - 1]; 1815 1816 if ((0,_util_isScheduler__WEBPACK_IMPORTED_MODULE_0__.isScheduler)(last)) { 1817 scheduler = observables.pop(); 1818 1819 if (observables.length > 1 && typeof observables[observables.length - 1] === 'number') { 1820 concurrent = observables.pop(); 1821 } 1822 } else if (typeof last === 'number') { 1823 concurrent = observables.pop(); 1824 } 1825 1826 if (scheduler === null && observables.length === 1 && observables[0] instanceof _Observable__WEBPACK_IMPORTED_MODULE_1__.Observable) { 1827 return observables[0]; 1828 } 1829 1830 return (0,_operators_mergeAll__WEBPACK_IMPORTED_MODULE_2__.mergeAll)(concurrent)((0,_fromArray__WEBPACK_IMPORTED_MODULE_3__.fromArray)(observables, scheduler)); 1831} 1832 1833/***/ }), 1834 1835/***/ 4139: 1836/*!**************************************************************!*\ 1837 !*** ./node_modules/rxjs/_esm2015/internal/observable/of.js ***! 1838 \**************************************************************/ 1839/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1840 1841__webpack_require__.r(__webpack_exports__); 1842/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1843/* harmony export */ "of": () => (/* binding */ of) 1844/* harmony export */ }); 1845/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isScheduler */ 7507); 1846/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./fromArray */ 8005); 1847/* harmony import */ var _scheduled_scheduleArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../scheduled/scheduleArray */ 8403); 1848 1849 1850 1851function of(...args) { 1852 let scheduler = args[args.length - 1]; 1853 1854 if ((0,_util_isScheduler__WEBPACK_IMPORTED_MODULE_0__.isScheduler)(scheduler)) { 1855 args.pop(); 1856 return (0,_scheduled_scheduleArray__WEBPACK_IMPORTED_MODULE_1__.scheduleArray)(args, scheduler); 1857 } else { 1858 return (0,_fromArray__WEBPACK_IMPORTED_MODULE_2__.fromArray)(args); 1859 } 1860} 1861 1862/***/ }), 1863 1864/***/ 6587: 1865/*!**********************************************************************!*\ 1866 !*** ./node_modules/rxjs/_esm2015/internal/observable/throwError.js ***! 1867 \**********************************************************************/ 1868/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1869 1870__webpack_require__.r(__webpack_exports__); 1871/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1872/* harmony export */ "throwError": () => (/* binding */ throwError) 1873/* harmony export */ }); 1874/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 2378); 1875 1876function throwError(error, scheduler) { 1877 if (!scheduler) { 1878 return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => subscriber.error(error)); 1879 } else { 1880 return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber =>
1880 scheduler.schedule(dispatch, 0, { 1881 error, 1882 subscriber 1883 })); 1884 } 1885} 1886 1887function dispatch({ 1888 error, 1889 subscriber 1890}) { 1891 subscriber.error(error); 1892} 1893 1894/***/ }), 1895 1896/***/ 7418: 1897/*!*********************************************************************!*\ 1898 !*** ./node_modules/rxjs/_esm2015/internal/operators/catchError.js ***! 1899 \*********************************************************************/ 1900/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1901 1902__webpack_require__.r(__webpack_exports__); 1903/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1904/* harmony export */ "catchError": () => (/* binding */ catchError) 1905/* harmony export */ }); 1906/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../innerSubscribe */ 2831); 1907 1908function catchError(selector) { 1909 return function catchErrorOperatorFunction(source) { 1910 const operator = new CatchOperator(selector); 1911 const caught = source.lift(operator); 1912 return operator.caught = caught; 1913 }; 1914} 1915 1916class CatchOperator { 1917 constructor(selector) { 1918 this.selector = selector; 1919 } 1920 1921 call(subscriber, source) { 1922 return source.subscribe(new CatchSubscriber(subscriber, this.selector, this.caught)); 1923 } 1924 1925} 1926 1927class CatchSubscriber extends _innerSubscribe__WEBPACK_IMPORTED_MODULE_0__.SimpleOuterSubscriber { 1928 constructor(destination, selector, caught) { 1929 super(destination); 1930 this.selector = selector; 1931 this.caught = caught; 1932 } 1933 1934 error(err) { 1935 if (!this.isStopped) { 1936 let result; 1937 1938 try { 1939 result = this.selector(err, this.caught); 1940 } catch (err2) { 1941 super.error(err2); 1942 return; 1943 } 1944 1945 this._unsubscribeAndRecycle(); 1946 1947 const innerSubscriber = new _innerSubscribe__WEBPACK_IMPORTED_MODULE_0__.SimpleInnerSubscriber(this); 1948 this.add(innerSubscriber); 1949 const innerSubscription = (0,_innerSubscribe__WEBPACK_IMPORTED_MODULE_0__.innerSubscribe)(result, innerSubscriber); 1950 1951 if (innerSubscription !== innerSubscriber) { 1952 this.add(innerSubscription); 1953 } 1954 } 1955 } 1956 1957} 1958 1959/***/ }), 1960 1961/***/ 2692: 1962/*!********************************************************************!*\ 1963 !*** ./node_modules/rxjs/_esm2015/internal/operators/concatAll.js ***! 1964 \********************************************************************/ 1965/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1966 1967__webpack_require__.r(__webpack_exports__); 1968/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1969/* harmony export */ "concatAll": () => (/* binding */ concatAll) 1970/* harmony export */ }); 1971/* harmony import */ var _mergeAll__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mergeAll */ 6675); 1972 1973function concatAll() { 1974 return (0,_mergeAll__WEBPACK_IMPORTED_MODULE_0__.mergeAll)(1); 1975} 1976 1977/***/ }), 1978 1979/***/ 1133: 1980/*!********************************************************************!*\ 1981 !*** ./node_modules/rxjs/_esm2015/internal/operators/concatMap.js ***! 1982 \********************************************************************/ 1983/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 1984 1985__webpack_require__.r(__webpack_exports__); 1986/* harmony export */ __webpack_require__.d(__webpack_exports__, { 1987/* harmony export */ "concatMap": () => (/* binding */ concatMap) 1988/* harmony export */ }); 1989/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mergeMap */ 522); 1990 1991function concatMap(project, resultSelector) { 1992 return (0,_mergeMap__WEBPACK_IMPORTED_MODULE_0__.mergeMap)(project, resultSelector, 1); 1993} 1994 1995/***/ }), 1996 1997/***/ 9701: 1998/*!*************************************************************************!*\ 1999 !*** ./node_modules/rxjs/_esm2015/internal/operators/defaultIfEmpty.js ***! 2000 \*************************************************************************/ 2001/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2002 2003__webpack_require__.r(__webpack_exports__); 2004/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2005/* harmony export */ "defaultIfEmpty": () => (/* binding */ defaultIfEmpty) 2006/* harmony export */ }); 2007/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscriber */ 14); 2008 2009function defaultIfEmpty(defaultValue = null) { 2010 return source =>
2010 source.lift(new DefaultIfEmptyOperator(defaultValue)); 2011} 2012 2013class DefaultIfEmptyOperator { 2014 constructor(defaultValue) { 2015 this.defaultValue = defaultValue; 2016 } 2017 2018 call(subscriber, source) { 2019 return source.subscribe(new DefaultIfEmptySubscriber(subscriber, this.defaultValue)); 2020 } 2021 2022} 2023 2024class DefaultIfEmptySubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 2025 constructor(destination, defaultValue) { 2026 super(destination); 2027 this.defaultValue = defaultValue; 2028 this.isEmpty = true; 2029 } 2030 2031 _next(value) { 2032 this.isEmpty = false; 2033 this.destination.next(value); 2034 } 2035 2036 _complete() { 2037 if (this.isEmpty) { 2038 this.destination.next(this.defaultValue); 2039 } 2040 2041 this.destination.complete(); 2042 } 2043 2044} 2045 2046/***/ }), 2047 2048/***/ 9151: 2049/*!*****************************************************************!*\ 2050 !*** ./node_modules/rxjs/_esm2015/internal/operators/filter.js ***! 2051 \*****************************************************************/ 2052/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2053 2054__webpack_require__.r(__webpack_exports__); 2055/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2056/* harmony export */ "filter": () => (/* binding */ filter) 2057/* harmony export */ }); 2058/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscriber */ 14); 2059 2060function filter(predicate, thisArg) { 2061 return function filterOperatorFunction(source) { 2062 return source.lift(new FilterOperator(predicate, thisArg)); 2063 }; 2064} 2065 2066class FilterOperator { 2067 constructor(predicate, thisArg) { 2068 this.predicate = predicate; 2069 this.thisArg = thisArg; 2070 } 2071 2072 call(subscriber, source) { 2073 return source.subscribe(new FilterSubscriber(subscriber, this.predicate, this.thisArg)); 2074 } 2075 2076} 2077 2078class FilterSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 2079 constructor(destination, predicate, thisArg) { 2080 super(destination); 2081 this.predicate = predicate; 2082 this.thisArg = thisArg; 2083 this.count = 0; 2084 } 2085 2086 _next(value) { 2087 let result; 2088 2089 try { 2090 result = this.predicate.call(this.thisArg, value, this.count++); 2091 } catch (err) { 2092 this.destination.error(err); 2093 return; 2094 } 2095 2096 if (result) { 2097 this.destination.next(value); 2098 } 2099 } 2100 2101} 2102 2103/***/ }), 2104 2105/***/ 4661: 2106/*!*******************************************************************!*\ 2107 !*** ./node_modules/rxjs/_esm2015/internal/operators/finalize.js ***! 2108 \*******************************************************************/ 2109/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2110 2111__webpack_require__.r(__webpack_exports__); 2112/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2113/* harmony export */ "finalize": () => (/* binding */ finalize) 2114/* harmony export */ }); 2115/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscriber */ 14); 2116/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Subscription */ 2425); 2117 2118 2119function finalize(callback) { 2120 return source => source.lift(new FinallyOperator(callback)); 2121} 2122 2123class FinallyOperator { 2124 constructor(callback) { 2125 this.callback = callback; 2126 } 2127 2128 call(subscriber, source) { 2129 return source.subscribe(new FinallySubscriber(subscriber, this.callback)); 2130 } 2131 2132} 2133 2134class FinallySubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 2135 constructor(destination, callback) { 2136 super(destination); 2137 this.add(new _Subscription__WEBPACK_IMPORTED_MODULE_1__.Subscription(callback)); 2138 } 2139 2140} 2141 2142/***/ }), 2143 2144/***/ 5670: 2145/*!****************************************************************!*\ 2146 !*** ./node_modules/rxjs/_esm2015/internal/operators/first.js ***! 2147 \****************************************************************/ 2148/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2149 2150__webpack_require__.r(__webpack_exports__); 2151/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2152/* harmony export */ "first": () => (/* binding */ first) 2153/* harmony export */ }); 2154/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../util/EmptyError */ 213); 2155/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./filter */ 9151); 2156/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./take */ 3910); 2157/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./defaultIfEmpty */ 9701); 2158/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./throwIfEmpty */ 2013); 2159/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/identity */ 1356); 2160 2161 2162 2163 2164 2165 2166function first(predicate, defaultValue) { 2167 const hasDefaultValue = arguments.length >= 2; 2168 return source => source.pipe(predicate ? (0,_filter__WEBPACK_IMPORTED_MODULE_0__.filter)((v, i) => predicate(v, i, source)) : _util_identity__WEBPACK_IMPORTED_MODULE_1__.identity, (0,_take__WEBPACK_IMPORTED_MODULE_2__.take)(1), hasDefaultValue ? (0,_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__.defaultIfEmpty)(defaultValue) : (0,_throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__.throwIfEmpty)(() => new _util_EmptyError__WEBPACK_IMPORTED_MODULE_5__.EmptyError())); 2169} 2170 2171/***/ }), 2172 2173/***/ 5690: 2174/*!***************************************************************!*\ 2175 !*** ./node_modules/rxjs/_esm2015/internal/operators/last.js ***! 2176 \***************************************************************/ 2177/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2178 2179__webpack_require__.r(__webpack_exports__); 2180/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2181/* harmony export */ "last": () => (/* binding */ last) 2182/* harmony export */ }); 2183/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../util/EmptyError */ 213); 2184/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./filter */ 9151); 2185/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./takeLast */ 7760); 2186/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./throwIfEmpty */ 2013); 2187/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./defaultIfEmpty */ 9701); 2188/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/identity */ 1356); 2189 2190 2191 2192 2193 2194 2195function last(predicate, defaultValue) { 2196 const hasDefaultValue = arguments.length >= 2; 2197 return source => source.pipe(predicate ? (0,_filter__WEBPACK_IMPORTED_MODULE_0__.filter)((v, i) => predicate(v, i, source)) : _util_identity__WEBPACK_IMPORTED_MODULE_1__.identity, (0,_takeLast__WEBPACK_IMPORTED_MODULE_2__.takeLast)(1), hasDefaultValue ? (0,_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__.defaultIfEmpty)(defaultValue) : (0,_throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__.throwIfEmpty)(() => new _util_EmptyError__WEBPACK_IMPORTED_MODULE_5__.EmptyError())); 2198} 2199 2200/***/ }), 2201 2202/***/ 6942: 2203/*!**************************************************************!*\ 2204 !*** ./node_modules/rxjs/_esm2015/internal/operators/map.js ***! 2205 \**************************************************************/ 2206/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2207 2208__webpack_require__.r(__webpack_exports__); 2209/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2210/* harmony export */ "MapOperator": () => (/* binding */ MapOperator), 2211/* harmony export */ "map": () => (/* binding */ map) 2212/* harmony export */ }); 2213/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscriber */ 14); 2214 2215function map(project, thisArg) { 2216 return function mapOperation(source) { 2217 if (typeof project !== 'function') { 2218 throw new TypeError('argument is not a function. Are you looking for `mapTo()`?'); 2219 } 2220 2221 return source.lift(new MapOperator(project, thisArg)); 2222 }; 2223} 2224class MapOperator { 2225 constructor(project, thisArg) { 2226 this.project = project; 2227 this.thisArg = thisArg; 2228 } 2229 2230 call(subscriber, source) { 2231 return source.subscribe(new MapSubscriber(subscriber, this.project, this.thisArg)); 2232 } 2233 2234} 2235 2236class MapSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 2237 constructor(destination, project, thisArg) { 2238 super(destination); 2239 this.project = project; 2240 this.count = 0; 2241 this.thisArg = thisArg || this; 2242 } 2243 2244 _next(value) { 2245 let result; 2246 2247 try { 2248 result = this.project.call(this.thisArg, value, this.count++); 2249 } catch (err) { 2250 this.destination.error(err); 2251 return; 2252 } 2253 2254 this.destination.next(result); 2255 } 2256 2257} 2258 2259/***/ }), 2260 2261/***/ 9361: 2262/*!****************************************************************!*\ 2263 !*** ./node_modules/rxjs/_esm2015/internal/operators/mapTo.js ***! 2264 \****************************************************************/ 2265/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2266 2267__webpack_require__.r(__webpack_exports__); 2268/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2269/* harmony export */ "mapTo": () => (/* binding */ mapTo) 2270/* harmony export */ }); 2271/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscriber */ 14); 2272 2273function mapTo(value) { 2274 return source => source.lift(new MapToOperator(value)); 2275} 2276 2277class MapToOperator { 2278 constructor(value) { 2279 this.value = value; 2280 } 2281 2282 call(subscriber, source) { 2283 return source.subscribe(new MapToSubscriber(subscriber, this.value)); 2284 } 2285 2286} 2287 2288class MapToSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 2289 constructor(destination, value) { 2290 super(destination); 2291 this.value = value; 2292 } 2293 2294 _next(x) { 2295 this.destination.next(this.value); 2296 } 2297 2298} 2299 2300/***/ }), 2301 2302/***/ 6675: 2303/*!*******************************************************************!*\ 2304 !*** ./node_modules/rxjs/_esm2015/internal/operators/mergeAll.js ***! 2305 \*******************************************************************/ 2306/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2307 2308__webpack_require__.r(__webpack_exports__); 2309/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2310/* harmony export */ "mergeAll": () => (/* binding */ mergeAll) 2311/* harmony export */ }); 2312/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mergeMap */ 522); 2313/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/identity */ 1356); 2314 2315 2316function mergeAll(concurrent = Number.POSITIVE_INFINITY) { 2317 return (0,_mergeMap__WEBPACK_IMPORTED_MODULE_0__.mergeMap)(_util_identity__WEBPACK_IMPORTED_MODULE_1__.identity, concurrent); 2318} 2319 2320/***/ }), 2321 2322/***/ 522: 2323/*!*******************************************************************!*\ 2324 !*** ./node_modules/rxjs/_esm2015/internal/operators/mergeMap.js ***! 2325 \*******************************************************************/ 2326/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2327 2328__webpack_require__.r(__webpack_exports__); 2329/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2330/* harmony export */ "MergeMapOperator": () => (/* binding */ MergeMapOperator),
2331/* harmony export */ "MergeMapSubscriber": () => (/* binding */ MergeMapSubscriber), 2332/* harmony export */ "flatMap": () => (/* binding */ flatMap), 2333/* harmony export */ "mergeMap": () => (/* binding */ mergeMap) 2334/* harmony export */ }); 2335/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./map */ 6942); 2336/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../observable/from */ 4383); 2337/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../innerSubscribe */ 2831); 2338 2339 2340 2341function mergeMap(project, resultSelector, concurrent = Number.POSITIVE_INFINITY) { 2342 if (typeof resultSelector === 'function') { 2343 return source => source.pipe(mergeMap((a, i) => (0,_observable_from__WEBPACK_IMPORTED_MODULE_0__.from)(project(a, i)).pipe((0,_map__WEBPACK_IMPORTED_MODULE_1__.map)((b, ii) => resultSelector(a, b, i, ii))), concurrent)); 2344 } else if (typeof resultSelector === 'number') { 2345 concurrent = resultSelector; 2346 } 2347 2348 return source => source.lift(new MergeMapOperator(project, concurrent)); 2349} 2350class MergeMapOperator { 2351 constructor(project, concurrent = Number.POSITIVE_INFINITY) { 2352 this.project = project; 2353 this.concurrent = concurrent; 2354 } 2355 2356 call(observer, source) { 2357 return source.subscribe(new MergeMapSubscriber(observer, this.project, this.concurrent)); 2358 } 2359 2360} 2361class MergeMapSubscriber extends _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__.SimpleOuterSubscriber { 2362 constructor(destination, project, concurrent = Number.POSITIVE_INFINITY) { 2363 super(destination); 2364 this.project = project; 2365 this.concurrent = concurrent; 2366 this.hasCompleted = false; 2367 this.buffer = []; 2368 this.active = 0; 2369 this.index = 0; 2370 } 2371 2372 _next(value) { 2373 if (this.active < this.concurrent) { 2374 this._tryNext(value); 2375 } else { 2376 this.buffer.push(value); 2377 } 2378 } 2379 2380 _tryNext(value) { 2381 let result; 2382 const index = this.index++; 2383 2384 try { 2385 result = this.project(value, index); 2386 } catch (err) { 2387 this.destination.error(err); 2388 return; 2389 } 2390 2391 this.active++; 2392 2393 this._innerSub(result); 2394 } 2395 2396 _innerSub(ish) { 2397 const innerSubscriber = new _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__.SimpleInnerSubscriber(this); 2398 const destination = this.destination; 2399 destination.add(innerSubscriber); 2400 const innerSubscription = (0,_innerSubscribe__WEBPACK_IMPORTED_MODULE_2__.innerSubscribe)(ish, innerSubscriber); 2401 2402 if (innerSubscription !== innerSubscriber) { 2403 destination.add(innerSubscription); 2404 } 2405 } 2406 2407 _complete() { 2408 this.hasCompleted = true; 2409 2410 if (this.active === 0 && this.buffer.length === 0) { 2411 this.destination.complete(); 2412 } 2413 2414 this.unsubscribe(); 2415 } 2416 2417 notifyNext(innerValue) { 2418 this.destination.next(innerValue); 2419 } 2420 2421 notifyComplete() { 2422 const buffer = this.buffer; 2423 this.active--; 2424 2425 if (buffer.length > 0) { 2426 this._next(buffer.shift()); 2427 } else if (this.active === 0 && this.hasCompleted) { 2428 this.destination.complete(); 2429 } 2430 } 2431 2432} 2433const flatMap = mergeMap; 2434 2435/***/ }), 2436 2437/***/ 2787: 2438/*!********************************************************************!*\ 2439 !*** ./node_modules/rxjs/_esm2015/internal/operators/multicast.js ***! 2440 \********************************************************************/ 2441/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2442 2443__webpack_require__.r(__webpack_exports__); 2444/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2445/* harmony export */ "MulticastOperator": () => (/* binding */ MulticastOperator), 2446/* harmony export */ "multicast": () => (/* binding */ multicast) 2447/* harmony export */ }); 2448/* harmony import */ var _observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../observable/ConnectableObservable */ 4483); 2449 2450function multicast(subjectOrSubjectFactory, selector) { 2451 return function multicastOperatorFunction(source) { 2452 let subjectFactory; 2453 2454 if (typeof subjectOrSubjectFactory === 'function') { 2455 subjectFactory = subjectOrSubjectFactory; 2456 } else { 2457 subjectFactory = function subjectFactory() { 2458 return subjectOrSubjectFactory; 2459 }; 2460 } 2461 2462 if (typeof selector === 'function') { 2463 return source.lift(new MulticastOperator(subjectFactory, selector)); 2464 } 2465 2466 const connectable = Object.create(source, _observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_0__.connectableObservableDescriptor); 2467 connectable.source = source; 2468 connectable.subjectFactory = subjectFactory; 2469 return connectable; 2470 }; 2471} 2472class MulticastOperator { 2473 constructor(subjectFactory, selector) { 2474 this.subjectFactory = subjectFactory; 2475 this.selector = selector; 2476 } 2477 2478 call(subscriber, source) { 2479 const { 2480 selector 2481 } = this; 2482 const subject = this.subjectFactory(); 2483 const subscription = selector(subject).subscribe(subscriber); 2484 subscription.add(source.subscribe(subject)); 2485 return subscription; 2486 } 2487 2488} 2489 2490/***/ }), 2491 2492/***/ 8331: 2493/*!*******************************************************************!*\ 2494 !*** ./node_modules/rxjs/_esm2015/internal/operators/refCount.js ***! 2495 \*******************************************************************/ 2496/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2497 2498__webpack_require__.r(__webpack_exports__); 2499/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2500/* harmony export */ "refCount": () => (/* binding */ refCount) 2501/* harmony export */ }); 2502/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscriber */ 14); 2503 2504function refCount() { 2505 return function refCountOperatorFunction(source) { 2506 return source.lift(new RefCountOperator(source)); 2507 }; 2508} 2509 2510class RefCountOperator { 2511 constructor(connectable) { 2512 this.connectable = connectable; 2513 } 2514 2515 call(subscriber, source) { 2516 const { 2517 connectable 2518 } = this; 2519 connectable._refCount++; 2520 const refCounter = new RefCountSubscriber(subscriber, connectable); 2521 const subscription = source.subscribe(refCounter); 2522 2523 if (!refCounter.closed) { 2524 refCounter.connection = connectable.connect(); 2525 } 2526 2527 return subscription; 2528 } 2529 2530} 2531 2532class RefCountSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 2533 constructor(destination, connectable) { 2534 super(destination); 2535 this.connectable = connectable; 2536 } 2537 2538 _unsubscribe() { 2539 const { 2540 connectable 2541 } = this; 2542 2543 if (!connectable) { 2544 this.connection = null; 2545 return; 2546 } 2547 2548 this.connectable = null; 2549 const refCount = connectable._refCount; 2550 2551 if (refCount <= 0) { 2552 this.connection = null; 2553 return; 2554 } 2555 2556 connectable._refCount = refCount - 1; 2557 2558 if (refCount > 1) { 2559 this.connection = null; 2560 return; 2561 } 2562 2563 const { 2564 connection 2565 } = this; 2566 const sharedConnection = connectable._connection; 2567 this.connection = null; 2568 2569 if (sharedConnection && (!connection || sharedConnection === connection)) { 2570 sharedConnection.unsubscribe(); 2571 } 2572 } 2573 2574} 2575 2576/***/ }), 2577 2578/***/ 2647: 2579/*!***************************************************************!*\ 2580 !*** ./node_modules/rxjs/_esm2015/internal/operators/scan.js ***! 2581 \***************************************************************/ 2582/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2583 2584__webpack_require__.r(__webpack_exports__); 2585/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2586/* harmony export */ "scan": () => (/* binding */ scan) 2587/* harmony export */ }); 2588/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscriber */ 14); 2589 2590function scan(accumulator, seed) { 2591 let hasSeed = false;
2592 2593 if (arguments.length >= 2) { 2594 hasSeed = true; 2595 } 2596 2597 return function scanOperatorFunction(source) { 2598 return source.lift(new ScanOperator(accumulator, seed, hasSeed)); 2599 }; 2600} 2601 2602class ScanOperator { 2603 constructor(accumulator, seed, hasSeed = false) { 2604 this.accumulator = accumulator; 2605 this.seed = seed; 2606 this.hasSeed = hasSeed; 2607 } 2608 2609 call(subscriber, source) { 2610 return source.subscribe(new ScanSubscriber(subscriber, this.accumulator, this.seed, this.hasSeed)); 2611 } 2612 2613} 2614 2615class ScanSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 2616 constructor(destination, accumulator, _seed, hasSeed) { 2617 super(destination); 2618 this.accumulator = accumulator; 2619 this._seed = _seed; 2620 this.hasSeed = hasSeed; 2621 this.index = 0; 2622 } 2623 2624 get seed() { 2625 return this._seed; 2626 } 2627 2628 set seed(value) { 2629 this.hasSeed = true; 2630 this._seed = value; 2631 } 2632 2633 _next(value) { 2634 if (!this.hasSeed) { 2635 this.seed = value; 2636 this.destination.next(value); 2637 } else { 2638 return this._tryNext(value); 2639 } 2640 } 2641 2642 _tryNext(value) { 2643 const index = this.index++; 2644 let result; 2645 2646 try { 2647 result = this.accumulator(this.seed, value, index); 2648 } catch (err) { 2649 this.destination.error(err); 2650 } 2651 2652 this.seed = result; 2653 this.destination.next(result); 2654 } 2655 2656} 2657 2658/***/ }), 2659 2660/***/ 4514: 2661/*!****************************************************************!*\ 2662 !*** ./node_modules/rxjs/_esm2015/internal/operators/share.js ***! 2663 \****************************************************************/ 2664/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2665 2666__webpack_require__.r(__webpack_exports__); 2667/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2668/* harmony export */ "share": () => (/* binding */ share) 2669/* harmony export */ }); 2670/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./multicast */ 2787); 2671/* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./refCount */ 8331); 2672/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subject */ 2218); 2673 2674 2675 2676 2677function shareSubjectFactory() { 2678 return new _Subject__WEBPACK_IMPORTED_MODULE_0__.Subject(); 2679} 2680 2681function share() { 2682 return source => (0,_refCount__WEBPACK_IMPORTED_MODULE_1__.refCount)()((0,_multicast__WEBPACK_IMPORTED_MODULE_2__.multicast)(shareSubjectFactory)(source)); 2683} 2684 2685/***/ }), 2686 2687/***/ 6276: 2688/*!***************************************************************!*\ 2689 !*** ./node_modules/rxjs/_esm2015/internal/operators/skip.js ***! 2690 \***************************************************************/ 2691/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2692 2693__webpack_require__.r(__webpack_exports__); 2694/* harmony export */ __webpack_require__.d(__webpack_exports__, {
2695/* harmony export */ "skip": () => (/* binding */ skip) 2696/* harmony export */ }); 2697/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscriber */ 14); 2698 2699function skip(count) { 2700 return source => source.lift(new SkipOperator(count)); 2701} 2702 2703class SkipOperator { 2704 constructor(total) { 2705 this.total = total; 2706 } 2707 2708 call(subscriber, source) { 2709 return source.subscribe(new SkipSubscriber(subscriber, this.total)); 2710 } 2711 2712} 2713 2714class SkipSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 2715 constructor(destination, total) { 2716 super(destination); 2717 this.total = total; 2718 this.count = 0; 2719 } 2720 2721 _next(x) { 2722 if (++this.count > this.total) { 2723 this.destination.next(x); 2724 } 2725 } 2726 2727} 2728 2729/***/ }), 2730 2731/***/ 5722: 2732/*!********************************************************************!*\ 2733 !*** ./node_modules/rxjs/_esm2015/internal/operators/startWith.js ***! 2734 \********************************************************************/ 2735/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2736 2737__webpack_require__.r(__webpack_exports__); 2738/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2739/* harmony export */ "startWith": () => (/* binding */ startWith) 2740/* harmony export */ }); 2741/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../observable/concat */ 5828); 2742/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isScheduler */ 7507); 2743 2744 2745function startWith(...array) { 2746 const scheduler = array[array.length - 1]; 2747 2748 if ((0,_util_isScheduler__WEBPACK_IMPORTED_MODULE_0__.isScheduler)(scheduler)) { 2749 array.pop(); 2750 return source => (0,_observable_concat__WEBPACK_IMPORTED_MODULE_1__.concat)(array, source, scheduler); 2751 } else { 2752 return source => (0,_observable_concat__WEBPACK_IMPORTED_MODULE_1__.concat)(array, source); 2753 } 2754} 2755 2756/***/ }), 2757 2758/***/ 9095: 2759/*!********************************************************************!*\ 2760 !*** ./node_modules/rxjs/_esm2015/internal/operators/switchMap.js ***! 2761 \********************************************************************/ 2762/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2763 2764__webpack_require__.r(__webpack_exports__); 2765/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2766/* harmony export */ "switchMap": () => (/* binding */ switchMap) 2767/* harmony export */ }); 2768/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./map */ 6942); 2769/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../observable/from */ 4383); 2770/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../innerSubscribe */ 2831); 2771 2772 2773 2774function switchMap(project, resultSelector) { 2775 if (typeof resultSelector === 'function') { 2776 return source => source.pipe(switchMap((a, i) => (0,_observable_from__WEBPACK_IMPORTED_MODULE_0__.from)(project(a, i)).pipe((0,_map__WEBPACK_IMPORTED_MODULE_1__.map)((b, ii) => resultSelector(a, b, i, ii))))); 2777 } 2778 2779 return source => source.lift(new SwitchMapOperator(project)); 2780} 2781 2782class SwitchMapOperator { 2783 constructor(project) { 2784 this.project = project; 2785 } 2786 2787 call(subscriber, source) { 2788 return source.subscribe(new SwitchMapSubscriber(subscriber, this.project)); 2789 } 2790 2791} 2792 2793class SwitchMapSubscriber extends _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__.SimpleOuterSubscriber { 2794 constructor(destination, project) { 2795 super(destination); 2796 this.project = project; 2797 this.index = 0; 2798 } 2799 2800 _next(value) { 2801 let result; 2802 const index = this.index++; 2803 2804 try { 2805 result = this.project(value, index); 2806 } catch (error) { 2807 this.destination.error(error); 2808 return; 2809 } 2810 2811 this._innerSub(result); 2812 } 2813 2814 _innerSub(result) { 2815 const innerSubscription = this.innerSubscription; 2816 2817 if (innerSubscription) { 2818 innerSubscription.unsubscribe(); 2819 } 2820 2821 const innerSubscriber = new _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__.SimpleInnerSubscriber(this); 2822 const destination = this.destination; 2823 destination.add(innerSubscriber); 2824 this.innerSubscription = (0,_innerSubscribe__WEBPACK_IMPORTED_MODULE_2__.innerSubscribe)(result, innerSubscriber); 2825 2826 if (this.innerSubscription !== innerSubscriber) { 2827 destination.add(this.innerSubscription); 2828 } 2829 } 2830 2831 _complete() { 2832 const { 2833 innerSubscription 2834 } = this; 2835 2836 if (!innerSubscription || innerSubscription.closed) { 2837 super._complete(); 2838 } 2839 2840 this.unsubscribe(); 2841 } 2842 2843 _unsubscribe() { 2844 this.innerSubscription = undefined; 2845 } 2846 2847 notifyComplete() { 2848 this.innerSubscription = undefined; 2849 2850 if (this.isStopped) { 2851 super._complete(); 2852 } 2853 } 2854 2855 notifyNext(innerValue) { 2856 this.destination.next(innerValue); 2857 } 2858 2859} 2860 2861/***/ }), 2862 2863/***/ 3910: 2864/*!***************************************************************!*\ 2865 !*** ./node_modules/rxjs/_esm2015/internal/operators/take.js ***! 2866 \***************************************************************/ 2867/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2868 2869__webpack_require__.r(__webpack_exports__); 2870/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2871/* harmony export */ "take": () => (/* binding */ take) 2872/* harmony export */ }); 2873/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Subscriber */ 14); 2874/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/ArgumentOutOfRangeError */ 2846); 2875/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../observable/empty */ 6439); 2876 2877 2878 2879function take(count) { 2880 return source => { 2881 if (count === 0) { 2882 return (0,_observable_empty__WEBPACK_IMPORTED_MODULE_0__.empty)(); 2883 } else { 2884 return source.lift(new TakeOperator(count)); 2885 } 2886 }; 2887} 2888 2889class TakeOperator { 2890 constructor(total) { 2891 this.total = total; 2892 2893 if (this.total < 0) { 2894 throw new _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_1__.ArgumentOutOfRangeError(); 2895 } 2896 } 2897 2898 call(subscriber, source) { 2899 return source.subscribe(new TakeSubscriber(subscriber, this.total)); 2900 } 2901 2902} 2903 2904class TakeSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_2__.Subscriber { 2905 constructor(destination, total) { 2906 super(destination); 2907 this.total = total; 2908 this.count = 0; 2909 } 2910 2911 _next(value) { 2912 const total = this.total; 2913 const count = ++this.count; 2914 2915 if (count <= total) { 2916 this.destination.next(value); 2917 2918 if (count === total) { 2919 this.destination.complete(); 2920 this.unsubscribe(); 2921 } 2922 } 2923 } 2924 2925} 2926 2927/***/ }), 2928 2929/***/ 7760: 2930/*!*******************************************************************!*\ 2931 !*** ./node_modules/rxjs/_esm2015/internal/operators/takeLast.js ***! 2932 \*******************************************************************/ 2933/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 2934 2935__webpack_require__.r(__webpack_exports__); 2936/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2937/* harmony export */ "takeLast": () => (/* binding */ takeLast) 2938/* harmony export */ }); 2939/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Subscriber */ 14); 2940/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/ArgumentOutOfRangeError */ 2846); 2941/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../observable/empty */ 6439); 2942 2943 2944 2945function takeLast(count) { 2946 return function takeLastOperatorFunction(source) { 2947 if (count === 0) { 2948 return (0,_observable_empty__WEBPACK_IMPORTED_MODULE_0__.empty)(); 2949 } else { 2950 return source.lift(new TakeLastOperator(count)); 2951 } 2952 }; 2953} 2954 2955class TakeLastOperator { 2956 constructor(total) { 2957 this.total = total; 2958 2959 if (this.total < 0) { 2960 throw new _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_1__.ArgumentOutOfRangeError(); 2961 } 2962 } 2963 2964 call(subscriber, source) { 2965 return source.subscribe(new TakeLastSubscriber(subscriber, this.total)); 2966 } 2967 2968} 2969 2970class TakeLastSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_2__.Subscriber { 2971 constructor(destination, total) { 2972 super(destination); 2973 this.total = total; 2974 this.ring = new Array(); 2975 this.count = 0; 2976 } 2977 2978 _next(value) { 2979 const ring = this.ring; 2980 const total = this.total; 2981 const count = this.count++; 2982 2983 if (ring.length < total) { 2984 ring.push(value); 2985 } else { 2986 const index = count % total; 2987 ring[index] = value; 2988 } 2989 } 2990 2991 _complete() { 2992 const destination = this.destination;
2993 let count = this.count; 2994 2995 if (count > 0) { 2996 const total = this.count >= this.total ? this.total : this.count; 2997 const ring = this.ring; 2998 2999 for (let i = 0; i < total; i++) { 3000 const idx = count++ % total; 3001 destination.next(ring[idx]); 3002 } 3003 } 3004 3005 destination.complete(); 3006 } 3007 3008} 3009 3010/***/ }), 3011 3012/***/ 5050: 3013/*!********************************************************************!*\ 3014 !*** ./node_modules/rxjs/_esm2015/internal/operators/takeWhile.js ***! 3015 \********************************************************************/ 3016/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3017 3018__webpack_require__.r(__webpack_exports__); 3019/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3020/* harmony export */ "takeWhile": () => (/* binding */ takeWhile) 3021/* harmony export */ }); 3022/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscriber */ 14); 3023 3024function takeWhile(predicate, inclusive = false) { 3025 return source => source.lift(new TakeWhileOperator(predicate, inclusive)); 3026} 3027 3028class TakeWhileOperator { 3029 constructor(predicate, inclusive) { 3030 this.predicate = predicate; 3031 this.inclusive = inclusive; 3032 } 3033 3034 call(subscriber, source) { 3035 return source.subscribe(new TakeWhileSubscriber(subscriber, this.predicate, this.inclusive)); 3036 } 3037 3038} 3039 3040class TakeWhileSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 3041 constructor(destination, predicate, inclusive) { 3042 super(destination); 3043 this.predicate = predicate; 3044 this.inclusive = inclusive; 3045 this.index = 0; 3046 } 3047 3048 _next(value) { 3049 const destination = this.destination; 3050 let result; 3051 3052 try { 3053 result = this.predicate(value, this.index++); 3054 } catch (err) { 3055 destination.error(err); 3056 return; 3057 } 3058 3059 this.nextOrComplete(value, result); 3060 } 3061 3062 nextOrComplete(value, predicateResult) { 3063 const destination = this.destination; 3064 3065 if (Boolean(predicateResult)) { 3066 destination.next(value); 3067 } else { 3068 if (this.inclusive) { 3069 destination.next(value); 3070 } 3071 3072 destination.complete(); 3073 } 3074 } 3075 3076} 3077 3078/***/ }), 3079 3080/***/ 8759: 3081/*!**************************************************************!*\ 3082 !*** ./node_modules/rxjs/_esm2015/internal/operators/tap.js ***! 3083 \**************************************************************/ 3084/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3085 3086__webpack_require__.r(__webpack_exports__); 3087/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3088/* harmony export */ "tap": () => (/* binding */ tap) 3089/* harmony export */ }); 3090/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscriber */ 14); 3091/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/noop */ 6882); 3092/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/isFunction */ 1900); 3093 3094 3095 3096function tap(nextOrObserver, error, complete) { 3097 return function tapOperatorFunction(source) { 3098 return source.lift(new DoOperator(nextOrObserver, error, complete)); 3099 }; 3100} 3101 3102class DoOperator { 3103 constructor(nextOrObserver, error, complete) { 3104 this.nextOrObserver = nextOrObserver; 3105 this.error = error; 3106 this.complete = complete; 3107 } 3108 3109 call(subscriber, source) { 3110 return source.subscribe(new TapSubscriber(subscriber, this.nextOrObserver, this.error, this.complete)); 3111 } 3112 3113} 3114 3115class TapSubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 3116 constructor(destination, observerOrNext, error, complete) { 3117 super(destination); 3118 this._tapNext = _util_noop__WEBPACK_IMPORTED_MODULE_1__.noop; 3119 this._tapError = _util_noop__WEBPACK_IMPORTED_MODULE_1__.noop; 3120 this._tapComplete = _util_noop__WEBPACK_IMPORTED_MODULE_1__.noop; 3121 this._tapError = error || _util_noop__WEBPACK_IMPORTED_MODULE_1__.noop; 3122 this._tapComplete = complete || _util_noop__WEBPACK_IMPORTED_MODULE_1__.noop; 3123 3124 if ((0,_util_isFunction__WEBPACK_IMPORTED_MODULE_2__.isFunction)(observerOrNext)) { 3125 this._context = this; 3126 this._tapNext = observerOrNext; 3127 } else if (observerOrNext) { 3128 this._context = observerOrNext; 3129 this._tapNext = observerOrNext.next || _util_noop__WEBPACK_IMPORTED_MODULE_1__.noop; 3130 this._tapError = observerOrNext.error || _util_noop__WEBPACK_IMPORTED_MODULE_1__.noop; 3131 this._tapComplete = observerOrNext.complete || _util_noop__WEBPACK_IMPORTED_MODULE_1__.noop; 3132 } 3133 } 3134 3135 _next(value) { 3136 try { 3137 this._tapNext.call(this._context, value); 3138 } catch (err) { 3139 this.destination.error(err); 3140 return; 3141 } 3142 3143 this.destination.next(value); 3144 } 3145 3146 _error(err) { 3147 try { 3148 this._tapError.call(this._context, err); 3149 } catch (err) { 3150 this.destination.error(err); 3151 return; 3152 } 3153 3154 this.destination.error(err); 3155 } 3156 3157 _complete() { 3158 try { 3159 this._tapComplete.call(this._context); 3160 } catch (err) { 3161 this.destination.error(err); 3162 return; 3163 } 3164 3165 return this.destination.complete(); 3166 } 3167 3168} 3169 3170/***/ }), 3171 3172/***/ 2013: 3173/*!***********************************************************************!*\ 3174 !*** ./node_modules/rxjs/_esm2015/internal/operators/throwIfEmpty.js ***! 3175 \***********************************************************************/ 3176/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3177 3178__webpack_require__.r(__webpack_exports__); 3179/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3180/* harmony export */ "throwIfEmpty": () => (/* binding */ throwIfEmpty) 3181/* harmony export */ }); 3182/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/EmptyError */ 213); 3183/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscriber */ 14); 3184 3185 3186function throwIfEmpty(errorFactory = defaultErrorFactory) { 3187 return source => {
3188 return source.lift(new ThrowIfEmptyOperator(errorFactory)); 3189 }; 3190} 3191 3192class ThrowIfEmptyOperator { 3193 constructor(errorFactory) { 3194 this.errorFactory = errorFactory; 3195 } 3196 3197 call(subscriber, source) { 3198 return source.subscribe(new ThrowIfEmptySubscriber(subscriber, this.errorFactory)); 3199 } 3200 3201} 3202 3203class ThrowIfEmptySubscriber extends _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber { 3204 constructor(destination, errorFactory) { 3205 super(destination); 3206 this.errorFactory = errorFactory; 3207 this.hasValue = false; 3208 } 3209 3210 _next(value) { 3211 this.hasValue = true; 3212 this.destination.next(value); 3213 } 3214 3215 _complete() { 3216 if (!this.hasValue) { 3217 let err; 3218 3219 try { 3220 err = this.errorFactory(); 3221 } catch (e) { 3222 err = e; 3223 } 3224 3225 this.destination.error(err); 3226 } else { 3227 return this.destination.complete(); 3228 } 3229 } 3230 3231} 3232 3233function defaultErrorFactory() { 3234 return new _util_EmptyError__WEBPACK_IMPORTED_MODULE_1__.EmptyError(); 3235} 3236 3237/***/ }), 3238 3239/***/ 8403: 3240/*!************************************************************************!*\ 3241 !*** ./node_modules/rxjs/_esm2015/internal/scheduled/scheduleArray.js ***! 3242 \************************************************************************/ 3243/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3244 3245__webpack_require__.r(__webpack_exports__); 3246/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3247/* harmony export */ "scheduleArray": () => (/* binding */ scheduleArray) 3248/* harmony export */ }); 3249/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 2378); 3250/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Subscription */ 2425); 3251 3252 3253function scheduleArray(input, scheduler) { 3254 return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => { 3255 const sub = new _Subscription__WEBPACK_IMPORTED_MODULE_1__.Subscription(); 3256 let i = 0; 3257 sub.add(scheduler.schedule(function () { 3258 if (i === input.length) { 3259 subscriber.complete(); 3260 return; 3261 } 3262 3263 subscriber.next(input[i++]); 3264 3265 if (!subscriber.closed) { 3266 sub.add(this.schedule()); 3267 } 3268 })); 3269 return sub; 3270 }); 3271} 3272 3273/***/ }), 3274 3275/***/ 1232: 3276/*!***************************************************************************!*\ 3277 !*** ./node_modules/rxjs/_esm2015/internal/scheduled/scheduleIterable.js ***! 3278 \***************************************************************************/ 3279/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3280 3281__webpack_require__.r(__webpack_exports__); 3282/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3283/* harmony export */ "scheduleIterable": () => (/* binding */ scheduleIterable) 3284/* harmony export */ }); 3285/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 2378); 3286/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Subscription */ 2425); 3287/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../symbol/iterator */ 2803); 3288 3289 3290 3291function scheduleIterable(input, scheduler) { 3292 if (!input) { 3293 throw new Error('Iterable cannot be null'); 3294 } 3295 3296 return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => { 3297 const sub = new _Subscription__WEBPACK_IMPORTED_MODULE_1__.Subscription(); 3298 let iterator; 3299 sub.add(() => { 3300 if (iterator && typeof iterator.return === 'function') { 3301 iterator.return(); 3302 } 3303 }); 3304 sub.add(scheduler.schedule(() => { 3305 iterator = input[_symbol_iterator__WEBPACK_IMPORTED_MODULE_2__.iterator](); 3306 sub.add(scheduler.schedule(function () { 3307 if (subscriber.closed) { 3308 return; 3309 } 3310 3311 let value; 3312 let done; 3313 3314 try { 3315 const result = iterator.next(); 3316 value = result.value; 3317 done = result.done; 3318 } catch (err) { 3319 subscriber.error(err); 3320 return; 3321 } 3322 3323 if (done) { 3324 subscriber.complete(); 3325 } else { 3326 subscriber.next(value); 3327 this.schedule(); 3328 } 3329 })); 3330 })); 3331 return sub; 3332 }); 3333} 3334 3335/***/ }), 3336 3337/***/ 1145: 3338/*!*****************************************************************************!*\ 3339 !*** ./node_modules/rxjs/_esm2015/internal/scheduled/scheduleObservable.js ***! 3340 \*****************************************************************************/ 3341/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3342 3343__webpack_require__.r(__webpack_exports__); 3344/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3345/* harmony export */ "scheduleObservable": () => (/* binding */ scheduleObservable) 3346/* harmony export */ }); 3347/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 2378); 3348/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Subscription */ 2425); 3349/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../symbol/observable */ 6831); 3350 3351 3352 3353function scheduleObservable(input, scheduler) { 3354 return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => { 3355 const sub = new _Subscription__WEBPACK_IMPORTED_MODULE_1__.Subscription(); 3356 sub.add(scheduler.schedule(() => { 3357 const observable = input[_symbol_observable__WEBPACK_IMPORTED_MODULE_2__.observable](); 3358 sub.add(observable.subscribe({ 3359 next(value) { 3360 sub.add(scheduler.schedule(() => subscriber.next(value))); 3361 }, 3362 3363 error(err) { 3364 sub.add(scheduler.schedule(() => subscriber.error(err))); 3365 }, 3366 3367 complete() { 3368 sub.add(scheduler.schedule(() => subscriber.complete())); 3369 } 3370 3371 })); 3372 })); 3373 return sub; 3374 }); 3375} 3376 3377/***/ }), 3378 3379/***/ 467: 3380/*!**************************************************************************!*\ 3381 !*** ./node_modules/rxjs/_esm2015/internal/scheduled/schedulePromise.js ***! 3382 \**************************************************************************/ 3383/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3384 3385__webpack_require__.r(__webpack_exports__); 3386/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3387/* harmony export */ "schedulePromise": () => (/* binding */ schedulePromise) 3388/* harmony export */ }); 3389/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Observable */ 2378); 3390/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Subscription */ 2425); 3391 3392 3393function schedulePromise(input, scheduler) { 3394 return new _Observable__WEBPACK_IMPORTED_MODULE_0__.Observable(subscriber => { 3395 const sub = new _Subscription__WEBPACK_IMPORTED_MODULE_1__.Subscription(); 3396 sub.add(scheduler.schedule(() => input.then(value => { 3397 sub.add(scheduler.schedule(() => { 3398 subscriber.next(value); 3399 sub.add(scheduler.schedule(() => subscriber.complete())); 3400 })); 3401 }, err => { 3402 sub.add(scheduler.schedule(() => subscriber.error(err))); 3403 }
3403))); 3404 return sub; 3405 }); 3406} 3407 3408/***/ }), 3409 3410/***/ 2476: 3411/*!********************************************************************!*\ 3412 !*** ./node_modules/rxjs/_esm2015/internal/scheduled/scheduled.js ***! 3413 \********************************************************************/ 3414/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3415 3416__webpack_require__.r(__webpack_exports__); 3417/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3418/* harmony export */ "scheduled": () => (/* binding */ scheduled) 3419/* harmony export */ }); 3420/* harmony import */ var _scheduleObservable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./scheduleObservable */ 1145); 3421/* harmony import */ var _schedulePromise__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./schedulePromise */ 467); 3422/* harmony import */ var _scheduleArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./scheduleArray */ 8403); 3423/* harmony import */ var _scheduleIterable__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./scheduleIterable */ 1232); 3424/* harmony import */ var _util_isInteropObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/isInteropObservable */ 5781); 3425/* harmony import */ var _util_isPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/isPromise */ 5192); 3426/* harmony import */ var _util_isArrayLike__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../util/isArrayLike */ 5122); 3427/* harmony import */ var _util_isIterable__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../util/isIterable */ 9674); 3428 3429 3430 3431 3432 3433 3434 3435 3436function scheduled(input, scheduler) { 3437 if (input != null) { 3438 if ((0,_util_isInteropObservable__WEBPACK_IMPORTED_MODULE_0__.isInteropObservable)(input)) { 3439 return (0,_scheduleObservable__WEBPACK_IMPORTED_MODULE_1__.scheduleObservable)(input, scheduler); 3440 } else if ((0,_util_isPromise__WEBPACK_IMPORTED_MODULE_2__.isPromise)(input)) { 3441 return (0,_schedulePromise__WEBPACK_IMPORTED_MODULE_3__.schedulePromise)(input, scheduler); 3442 } else if ((0,_util_isArrayLike__WEBPACK_IMPORTED_MODULE_4__.isArrayLike)(input)) { 3443 return (0,_scheduleArray__WEBPACK_IMPORTED_MODULE_5__.scheduleArray)(input, scheduler); 3444 } else if ((0,_util_isIterable__WEBPACK_IMPORTED_MODULE_6__.isIterable)(input) || typeof input === 'string') { 3445 return (0,_scheduleIterable__WEBPACK_IMPORTED_MODULE_7__.scheduleIterable)(input, scheduler); 3446 } 3447 } 3448 3449 throw new TypeError((input !== null && typeof input || input) + ' is not observable'); 3450} 3451 3452/***/ }), 3453 3454/***/ 2803: 3455/*!****************************************************************!*\ 3456 !*** ./node_modules/rxjs/_esm2015/internal/symbol/iterator.js ***! 3457 \****************************************************************/ 3458/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3459 3460__webpack_require__.r(__webpack_exports__); 3461/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3462/* harmony export */ "$$iterator": () => (/* binding */ $$iterator), 3463/* harmony export */ "getSymbolIterator": () => (/* binding */ getSymbolIterator), 3464/* harmony export */ "iterator": () => (/* binding */ iterator) 3465/* harmony export */ }); 3466function getSymbolIterator() { 3467 if (typeof Symbol !== 'function' || !Symbol.iterator) { 3468 return '@@iterator'; 3469 } 3470 3471 return Symbol.iterator; 3472} 3473const iterator = getSymbolIterator(); 3474const $$iterator = iterator; 3475 3476/***/ }), 3477 3478/***/ 6831: 3479/*!******************************************************************!*\ 3480 !*** ./node_modules/rxjs/_esm2015/internal/symbol/observable.js ***! 3481 \******************************************************************/ 3482/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3483 3484__webpack_require__.r(__webpack_exports__); 3485/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3486/* harmony export */ "observable": () => (/* binding */ observable) 3487/* harmony export */ }); 3488const observable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')(); 3489 3490/***/ }), 3491 3492/***/ 1482: 3493/*!********************************************************************!*\ 3494 !*** ./node_modules/rxjs/_esm2015/internal/symbol/rxSubscriber.js ***! 3495 \********************************************************************/ 3496/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3497 3498__webpack_require__.r(__webpack_exports__); 3499/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3500/* harmony export */ "$$rxSubscriber": () => (/* binding */ $$rxSubscriber), 3501/* harmony export */ "rxSubscriber": () => (/* binding */ rxSubscriber) 3502/* harmony export */ }); 3503const rxSubscriber = (() => typeof Symbol === 'function' ? Symbol('rxSubscriber') : '@@rxSubscriber_' + Math.random())(); 3504const $$rxSubscriber = rxSubscriber; 3505 3506/***/ }), 3507 3508/***/ 2846: 3509/*!*****************************************************************************!*\ 3510 !*** ./node_modules/rxjs/_esm2015/internal/util/ArgumentOutOfRangeError.js ***! 3511 \*****************************************************************************/ 3512/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3513 3514__webpack_require__.r(__webpack_exports__); 3515/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3516/* harmony export */ "ArgumentOutOfRangeError": () => (/* binding */ ArgumentOutOfRangeError) 3517/* harmony export */ }); 3518const ArgumentOutOfRangeErrorImpl = (() => { 3519 function ArgumentOutOfRangeErrorImpl() { 3520 Error.call(this); 3521 this.message = 'argument out of range'; 3522 this.name = 'ArgumentOutOfRangeError'; 3523 return this; 3524 } 3525 3526 ArgumentOutOfRangeErrorImpl.prototype = Object.create(Error.prototype); 3527 return ArgumentOutOfRangeErrorImpl; 3528})(); 3529 3530const ArgumentOutOfRangeError = ArgumentOutOfRangeErrorImpl; 3531 3532/***/ }), 3533 3534/***/ 213: 3535/*!****************************************************************!*\ 3536 !*** ./node_modules/rxjs/_esm2015/internal/util/EmptyError.js ***! 3537 \****************************************************************/ 3538/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3539 3540__webpack_require__.r(__webpack_exports__); 3541/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3542/* harmony export */ "EmptyError": () => (/* binding */ EmptyError) 3543/* harmony export */ }); 3544const EmptyErrorImpl = (() => { 3545 function EmptyErrorImpl() { 3546 Error.call(this); 3547 this.message = 'no elements in sequence'; 3548 this.name = 'EmptyError'; 3549 return this; 3550 } 3551 3552 EmptyErrorImpl.prototype = Object.create(Error.prototype); 3553 return EmptyErrorImpl; 3554})(); 3555 3556const EmptyError = EmptyErrorImpl; 3557 3558/***/ }), 3559 3560/***/ 9086: 3561/*!*****************************************************************************!*\ 3562 !*** ./node_modules/rxjs/_esm2015/internal/util/ObjectUnsubscribedError.js ***! 3563 \*****************************************************************************/ 3564/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3565 3566__webpack_require__.r(__webpack_exports__); 3567/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3568/* harmony export */ "ObjectUnsubscribedError": () => (/* binding */ ObjectUnsubscribedError) 3569/* harmony export */ }); 3570const ObjectUnsubscribedErrorImpl = (() => { 3571 function ObjectUnsubscribedErrorImpl() { 3572 Error.call(this); 3573 this.message = 'object unsubscribed'; 3574 this.name = 'ObjectUnsubscribedError'; 3575 return this; 3576 } 3577 3578 ObjectUnsubscribedErrorImpl.prototype = Object.create(Error.prototype); 3579 return ObjectUnsubscribedErrorImpl; 3580})(); 3581 3582const ObjectUnsubscribedError = ObjectUnsubscribedErrorImpl; 3583 3584/***/ }), 3585 3586/***/ 7875: 3587/*!*************************************************************************!*\ 3588 !*** ./node_modules/rxjs/_esm2015/internal/util/UnsubscriptionError.js ***! 3589 \*************************************************************************/ 3590/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3591 3592__webpack_require__.r(__webpack_exports__); 3593/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3594/* harmony export */ "UnsubscriptionError": () => (/* binding */ UnsubscriptionError) 3595/* harmony export */ }); 3596const UnsubscriptionErrorImpl = (() => { 3597 function UnsubscriptionErrorImpl(errors) { 3598 Error.call(this); 3599 this.message = errors ? `${errors.length} errors occurred during unsubscription: 3600${errors.map((err, i) => `${i + 1}) ${err.toString()}`).join('\n ')}` : ''; 3601 this.name = 'UnsubscriptionError'; 3602 this.errors = errors; 3603 return this; 3604 } 3605 3606 UnsubscriptionErrorImpl.prototype = Object.create(Error.prototype); 3607 return UnsubscriptionErrorImpl; 3608})(); 3609 3610const UnsubscriptionError = UnsubscriptionErrorImpl; 3611 3612/***/ }), 3613 3614/***/ 5739: 3615/*!********************************************************************!*\ 3616 !*** ./node_modules/rxjs/_esm2015/internal/util/canReportError.js ***! 3617 \********************************************************************/ 3618/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3619 3620__webpack_require__.r(__webpack_exports__); 3621/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3622/* harmony export */ "canReportError": () => (/* binding */ canReportError) 3623/* harmony export */ }); 3624/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscriber */ 14); 3625 3626function canReportError(observer) { 3627 while (observer) { 3628 const { 3629 closed, 3630 destination, 3631 isStopped 3632 } = observer; 3633 3634 if (closed || isStopped) { 3635 return false;
3636 } else if (destination && destination instanceof _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber) { 3637 observer = destination; 3638 } else { 3639 observer = null; 3640 } 3641 } 3642 3643 return true; 3644} 3645 3646/***/ }), 3647 3648/***/ 8897: 3649/*!*********************************************************************!*\ 3650 !*** ./node_modules/rxjs/_esm2015/internal/util/hostReportError.js ***! 3651 \*********************************************************************/ 3652/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3653 3654__webpack_require__.r(__webpack_exports__); 3655/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3656/* harmony export */ "hostReportError": () => (/* binding */ hostReportError) 3657/* harmony export */ }); 3658function hostReportError(err) { 3659 setTimeout(() => { 3660 throw err; 3661 }, 0); 3662} 3663 3664/***/ }), 3665 3666/***/ 1356: 3667/*!**************************************************************!*\ 3668 !*** ./node_modules/rxjs/_esm2015/internal/util/identity.js ***! 3669 \**************************************************************/ 3670/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3671 3672__webpack_require__.r(__webpack_exports__); 3673/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3674/* harmony export */ "identity": () => (/* binding */ identity) 3675/* harmony export */ }); 3676function identity(x) { 3677 return x; 3678} 3679 3680/***/ }), 3681 3682/***/ 4327: 3683/*!*************************************************************!*\ 3684 !*** ./node_modules/rxjs/_esm2015/internal/util/isArray.js ***! 3685 \*************************************************************/ 3686/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3687 3688__webpack_require__.r(__webpack_exports__); 3689/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3690/* harmony export */ "isArray": () => (/* binding */ isArray) 3691/* harmony export */ }); 3692const isArray = (() => Array.isArray || (x => x && typeof x.length === 'number'))(); 3693 3694/***/ }), 3695 3696/***/ 5122: 3697/*!*****************************************************************!*\ 3698 !*** ./node_modules/rxjs/_esm2015/internal/util/isArrayLike.js ***! 3699 \*****************************************************************/ 3700/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3701 3702__webpack_require__.r(__webpack_exports__); 3703/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3704/* harmony export */ "isArrayLike": () => (/* binding */ isArrayLike) 3705/* harmony export */ }); 3706const isArrayLike = x => x && typeof x.length === 'number' && typeof x !== 'function'; 3707 3708/***/ }), 3709 3710/***/ 1900: 3711/*!****************************************************************!*\ 3712 !*** ./node_modules/rxjs/_esm2015/internal/util/isFunction.js ***! 3713 \****************************************************************/ 3714/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3715 3716__webpack_require__.r(__webpack_exports__); 3717/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3718/* harmony export */ "isFunction": () => (/* binding */ isFunction) 3719/* harmony export */ }); 3720function isFunction(x) { 3721 return typeof x === 'function'; 3722} 3723 3724/***/ }), 3725 3726/***/ 5781: 3727/*!*************************************************************************!*\ 3728 !*** ./node_modules/rxjs/_esm2015/internal/util/isInteropObservable.js ***! 3729 \*************************************************************************/ 3730/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3731 3732__webpack_require__.r(__webpack_exports__); 3733/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3734/* harmony export */ "isInteropObservable": () => (/* binding */ isInteropObservable) 3735/* harmony export */ }); 3736/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../symbol/observable */ 6831); 3737 3738function isInteropObservable(input) { 3739 return input && typeof input[_symbol_observable__WEBPACK_IMPORTED_MODULE_0__.observable] === 'function'; 3740} 3741 3742/***/ }), 3743 3744/***/ 9674: 3745/*!****************************************************************!*\ 3746 !*** ./node_modules/rxjs/_esm2015/internal/util/isIterable.js ***! 3747 \****************************************************************/ 3748/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3749 3750__webpack_require__.r(__webpack_exports__); 3751/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3752/* harmony export */ "isIterable": () => (/* binding */ isIterable) 3753/* harmony export */ }); 3754/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../symbol/iterator */ 2803); 3755 3756function isIterable(input) { 3757 return input && typeof input[_symbol_iterator__WEBPACK_IMPORTED_MODULE_0__.iterator] === 'function'; 3758} 3759 3760/***/ }), 3761 3762/***/ 6549: 3763/*!**************************************************************!*\ 3764 !*** ./node_modules/rxjs/_esm2015/internal/util/isObject.js ***! 3765 \**************************************************************/ 3766/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3767 3768__webpack_require__.r(__webpack_exports__); 3769/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3770/* harmony export */ "isObject": () => (/* binding */ isObject) 3771/* harmony export */ }); 3772function isObject(x) { 3773 return x !== null && typeof x === 'object'; 3774} 3775 3776/***/ }), 3777 3778/***/ 5192: 3779/*!***************************************************************!*\ 3780 !*** ./node_modules/rxjs/_esm2015/internal/util/isPromise.js ***! 3781 \***************************************************************/ 3782/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3783 3784__webpack_require__.r(__webpack_exports__); 3785/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3786/* harmony export */ "isPromise": () => (/* binding */ isPromise) 3787/* harmony export */ }); 3788function isPromise(value) { 3789 return !!value && typeof value.subscribe !== 'function' && typeof value.then === 'function'; 3790} 3791 3792/***/ }), 3793 3794/***/ 7507: 3795/*!*****************************************************************!*\ 3796 !*** ./node_modules/rxjs/_esm2015/internal/util/isScheduler.js ***! 3797 \*****************************************************************/ 3798/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3799 3800__webpack_require__.r(__webpack_exports__); 3801/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3802/* harmony export */ "isScheduler": () => (/* binding */ isScheduler) 3803/* harmony export */ }); 3804function isScheduler(value) { 3805 return value && typeof value.schedule === 'function'; 3806} 3807 3808/***/ }), 3809 3810/***/ 6882: 3811/*!**********************************************************!*\ 3812 !*** ./node_modules/rxjs/_esm2015/internal/util/noop.js ***! 3813 \**********************************************************/ 3814/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3815 3816__webpack_require__.r(__webpack_exports__); 3817/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3818/* harmony export */ "noop": () => (/* binding */ noop) 3819/* harmony export */ }); 3820function noop() {} 3821 3822/***/ }), 3823 3824/***/ 6800: 3825/*!**********************************************************!*\ 3826 !*** ./node_modules/rxjs/_esm2015/internal/util/pipe.js ***! 3827 \**********************************************************/ 3828/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3829 3830__webpack_require__.r(__webpack_exports__); 3831/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3832/* harmony export */ "pipe": () => (/* binding */ pipe), 3833/* harmony export */ "pipeFromArray": () => (/* binding */ pipeFromArray) 3834/* harmony export */ }); 3835/* harmony import */ var _identity__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./identity */ 1356); 3836 3837function pipe(...fns) { 3838 return pipeFromArray(fns); 3839} 3840function pipeFromArray(fns) { 3841 if (fns.length === 0) { 3842 return _identity__WEBPACK_IMPORTED_MODULE_0__.identity; 3843 } 3844 3845 if (fns.length === 1) { 3846 return fns[0]; 3847 } 3848 3849 return function piped(input) { 3850 return fns.reduce((prev, fn) => fn(prev), input); 3851 }; 3852} 3853 3854/***/ }), 3855 3856/***/ 6983: 3857/*!*****************************************************************!*\ 3858 !*** ./node_modules/rxjs/_esm2015/internal/util/subscribeTo.js ***! 3859 \*****************************************************************/ 3860/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3861 3862__webpack_require__.r(__webpack_exports__); 3863/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3864/* harmony export */ "subscribeTo": () => (/* binding */ subscribeTo) 3865/* harmony export */ }); 3866/* harmony import */ var _subscribeToArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./subscribeToArray */ 5414); 3867/* harmony import */ var _subscribeToPromise__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./subscribeToPromise */ 4276); 3868/* harmony import */ var _subscribeToIterable__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./subscribeToIterable */ 6473); 3869/* harmony import */ var _subscribeToObservable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./subscribeToObservable */ 1492); 3870/* harmony import */ var _isArrayLike__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./isArrayLike */ 5122); 3871/* harmony import */ var _isPromise__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./isPromise */ 5192); 3872/* harmony import */ var _isObject__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./isObject */ 6549); 3873/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../symbol/iterator */ 2803); 3874/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../symbol/observable */ 6831); 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884const subscribeTo = result => { 3885 if (!!result && typeof result[_symbol_observable__WEBPACK_IMPORTED_MODULE_0__.observable] === 'function') { 3886 return (0,_subscribeToObservable__WEBPACK_IMPORTED_MODULE_1__.subscribeToObservable)(result); 3887 } else if ((0,_isArrayLike__WEBPACK_IMPORTED_MODULE_2__.isArrayLike)(result)) { 3888 return (0,_subscribeToArray__WEBPACK_IMPORTED_MODULE_3__.subscribeToArray)(result); 3889 } else if ((0,_isPromise__WEBPACK_IMPORTED_MODULE_4__.isPromise)(result)) { 3890 return (0,_subscribeToPromise__WEBPACK_IMPORTED_MODULE_5__.subscribeToPromise)(result); 3891 } else if (!!result && typeof result[_symbol_iterator__WEBPACK_IMPORTED_MODULE_6__.iterator] === 'function') { 3892 return (0,_subscribeToIterable__WEBPACK_IMPORTED_MODULE_7__.subscribeToIterable)(result); 3893 } else { 3894 const value = (0,_isObject__WEBPACK_IMPORTED_MODULE_8__.isObject)(result) ? 'an invali
3894d object' : `'${result}'`; 3895 const msg = `You provided ${value} where a stream was expected.` + ' You can provide an Observable, Promise, Array, or Iterable.'; 3896 throw new TypeError(msg); 3897 } 3898}; 3899 3900/***/ }), 3901 3902/***/ 5414: 3903/*!**********************************************************************!*\ 3904 !*** ./node_modules/rxjs/_esm2015/internal/util/subscribeToArray.js ***! 3905 \**********************************************************************/ 3906/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3907 3908__webpack_require__.r(__webpack_exports__); 3909/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3910/* harmony export */ "subscribeToArray": () => (/* binding */ subscribeToArray) 3911/* harmony export */ }); 3912const subscribeToArray = array => subscriber => { 3913 for (let i = 0, len = array.length; i < len && !subscriber.closed; i++) { 3914 subscriber.next(array[i]); 3915 } 3916 3917 subscriber.complete(); 3918}; 3919 3920/***/ }), 3921 3922/***/ 6473: 3923/*!*************************************************************************!*\ 3924 !*** ./node_modules/rxjs/_esm2015/internal/util/subscribeToIterable.js ***! 3925 \*************************************************************************/ 3926/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3927 3928__webpack_require__.r(__webpack_exports__); 3929/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3930/* harmony export */ "subscribeToIterable": () => (/* binding */ subscribeToIterable) 3931/* harmony export */ }); 3932/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../symbol/iterator */ 2803); 3933 3934const subscribeToIterable = iterable => subscriber => { 3935 const iterator = iterable[_symbol_iterator__WEBPACK_IMPORTED_MODULE_0__.iterator](); 3936 3937 do { 3938 let item; 3939 3940 try { 3941 item = iterator.next(); 3942 } catch (err) { 3943 subscriber.error(err); 3944 return subscriber; 3945 } 3946 3947 if (item.done) { 3948 subscriber.complete(); 3949 break; 3950 } 3951 3952 subscriber.next(item.value); 3953 3954 if (subscriber.closed) { 3955 break; 3956 } 3957 } while (true); 3958 3959 if (typeof iterator.return === 'function') { 3960 subscriber.add(() => { 3961 if (iterator.return) { 3962 iterator.return(); 3963 } 3964 }); 3965 } 3966 3967 return subscriber; 3968}; 3969 3970/***/ }), 3971 3972/***/ 1492: 3973/*!***************************************************************************!*\ 3974 !*** ./node_modules/rxjs/_esm2015/internal/util/subscribeToObservable.js ***! 3975 \***************************************************************************/ 3976/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 3977 3978__webpack_require__.r(__webpack_exports__); 3979/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3980/* harmony export */ "subscribeToObservable": () => (/* binding */ subscribeToObservable) 3981/* harmony export */ }); 3982/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../symbol/observable */ 6831); 3983 3984const subscribeToObservable = obj => subscriber => { 3985 const obs = obj[_symbol_observable__WEBPACK_IMPORTED_MODULE_0__.observable](); 3986 3987 if (typeof obs.subscribe !== 'function') { 3988 throw new TypeError('Provided object does not correctly implement Symbol.observable'); 3989 } else { 3990 return obs.subscribe(subscriber); 3991 } 3992}; 3993 3994/***/ }), 3995 3996/***/ 4276: 3997/*!************************************************************************!*\ 3998 !*** ./node_modules/rxjs/_esm2015/internal/util/subscribeToPromise.js ***! 3999 \************************************************************************/ 4000/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 4001 4002__webpack_require__.r(__webpack_exports__); 4003/* harmony export */ __webpack_require__.d(__webpack_exports__, { 4004/* harmony export */ "subscribeToPromise": () => (/* binding */ subscribeToPromise) 4005/* harmony export */ }); 4006/* harmony import */ var _hostReportError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./hostReportError */ 8897); 4007 4008const subscribeToPromise = promise => subscriber => { 4009 promise.then(value => { 4010 if (!subscriber.closed) { 4011 subscriber.next(value); 4012 subscriber.complete(); 4013 } 4014 }, err => subscriber.error(err)).then(null, _hostReportError__WEBPACK_IMPORTED_MODULE_0__.hostReportError); 4015 return subscriber; 4016}; 4017 4018/***/ }), 4019 4020/***/ 640: 4021/*!***********************************************************************!*\ 4022 !*** ./node_modules/rxjs/_esm2015/internal/util/subscribeToResult.js ***! 4023 \***********************************************************************/ 4024/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 4025 4026__webpack_require__.r(__webpack_exports__); 4027/* harmony export */ __webpack_require__.d(__webpack_exports__, { 4028/* harmony export */ "subscribeToResult": () => (/* binding */ subscribeToResult) 4029/* harmony export */ }); 4030/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../InnerSubscriber */ 472); 4031/* harmony import */ var _subscribeTo__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./subscribeTo */ 6983); 4032/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Observable */ 2378); 4033 4034 4035 4036function subscribeToResult(outerSubscriber, result, outerValue, outerIndex, innerSubscriber = new _InnerSubscriber__WEBPACK_IMPORTED_MODULE_0__.InnerSubscriber(outerSubscriber, outerValue, outerIndex)) { 4037 if (innerSubscriber.closed) { 4038 return undefined; 4039 } 4040 4041 if (result instanceof _Observable__WEBPACK_IMPORTED_MODULE_1__.Observable) { 4042 return result.subscribe(innerSubscriber); 4043 } 4044 4045 return (0,_subscribeTo__WEBPACK_IMPORTED_MODULE_2__.subscribeTo)(result)(innerSubscriber); 4046} 4047 4048/***/ }), 4049 4050/***/ 8333: 4051/*!******************************************************************!*\ 4052 !*** ./node_modules/rxjs/_esm2015/internal/util/toSubscriber.js ***! 4053 \******************************************************************/ 4054/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 4055 4056__webpack_require__.r(__webpack_exports__); 4057/* harmony export */ __webpack_require__.d(__webpack_exports__, { 4058/* harmony export */ "toSubscriber": () => (/* binding */ toSubscriber) 4059/* harmony export */ }); 4060/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Subscriber */ 14); 4061/* harmony import */ var _symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../symbol/rxSubscriber */ 1482); 4062/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Observer */ 9957); 4063 4064 4065 4066function toSubscriber(nextOrObserver, error, complete) { 4067 if (nextOrObserver) { 4068 if (nextOrObserver instanceof _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber) { 4069 return nextOrObserver; 4070 } 4071 4072 if (nextOrObserver[_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__.rxSubscriber]) { 4073 return nextOrObserver[_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__.rxSubscriber](); 4074 } 4075 } 4076 4077 if (!nextOrObserver && !error && !complete) { 4078 return new _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber(_Observer__WEBPACK_IMPORTED_MODULE_2__.empty); 4079 } 4080 4081 return new _Subscriber__WEBPACK_IMPORTED_MODULE_0__.Subscriber(nextOrObserver, error, complete); 4082} 4083 4084/***/ }), 4085 4086/***/ 4929: 4087/*!*****************************************!*\ 4088 !*** ./node_modules/tslib/tslib.es6.js ***! 4089 \*****************************************/ 4090/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 4091 4092__webpack_require__.r(__webpack_exports__); 4093/* harmony export */ __webpack_require__.d(__webpack_exports__, { 4094/* harmony export */ "__assign": () => (/* binding */ __assign), 4095/* harmony export */ "__asyncDelegator": () => (/* binding */ __asyncDelegator), 4096/* harmony export */ "__asyncGenerator": () => (/* binding */ __asyncGenerator), 4097/* harmony export */ "__asyncValues": () => (/* binding */ __asyncValues), 4098/* harmony export */ "__await": () => (/* binding */ __await), 4099/* harmony export */ "__awaiter": () => (/* binding */ __awaiter), 4100/* harmony export */ "__classPrivateFieldGet": () => (/* binding */ __classPrivateFieldGet), 4101/* harmony export */ "__classPrivateFieldSet": () => (/* binding */ __classPrivateFieldSet), 4102/* harmony export */ "__createBinding": () => (/* binding */ __createBinding),
vendor: 4,739 bytes, lines 4103-4192
4103/* harmony export */ "__decorate": () => (/* binding */ __decorate), 4104/* harmony export */ "__exportStar": () => (/* binding */ __exportStar), 4105/* harmony export */ "__extends": () => (/* binding */ __extends), 4106/* harmony export */ "__generator": () => (/* binding */ __generator), 4107/* harmony export */ "__importDefault": () => (/* binding */ __importDefault), 4108/* harmony export */ "__importStar": () => (/* binding */ __importStar), 4109/* harmony export */ "__makeTemplateObject": () => (/* binding */ __makeTemplateObject), 4110/* harmony export */ "__metadata": () => (/* binding */ __metadata), 4111/* harmony export */ "__param": () => (/* binding */ __param), 4112/* harmony export */ "__read": () => (/* binding */ __read), 4113/* harmony export */ "__rest": () => (/* binding */ __rest), 4114/* harmony export */ "__spread": () => (/* binding */ __spread), 4115/* harmony export */ "__spreadArrays": () => (/* binding */ __spreadArrays), 4116/* harmony export */ "__values": () => (/* binding */ __values) 4117/* harmony export */ }); 4118/*! ***************************************************************************** 4119Copyright (c) Microsoft Corporation. 4120 4121Permission to use, copy, modify, and/or distribute this software for any 4122purpose with or without fee is hereby granted. 4123 4124THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 4125REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 4126AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 4127INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 4128LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 4129OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 4130PERFORMANCE OF THIS SOFTWARE. 4131***************************************************************************** */ 4132/* global Reflect, Promise */ 4133 4134var extendStatics = function(d, b) { 4135 extendStatics = Object.setPrototypeOf || 4136 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 4137 function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; 4138 return extendStatics(d, b); 4139}; 4140 4141function __extends(d, b) { 4142 extendStatics(d, b); 4143 function __() { this.constructor = d; } 4144 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 4145} 4146 4147var __assign = function() { 4148 __assign = Object.assign || function __assign(t) { 4149 for (var s, i = 1, n = arguments.length; i < n; i++) { 4150 s = arguments[i]; 4151 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 4152 } 4153 return t; 4154 } 4155 return __assign.apply(this, arguments); 4156} 4157 4158function __rest(s, e) { 4159 var t = {}; 4160 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) 4161 t[p] = s[p]; 4162 if (s != null && typeof Object.getOwnPropertySymbols === "function") 4163 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { 4164 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) 4165 t[p[i]] = s[p[i]]; 4166 } 4167 return t; 4168} 4169 4170function __decorate(decorators, target, key, desc) { 4171 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4172 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4173 else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 4174 return c > 3 && r && Object.defineProperty(target, key, r), r; 4175} 4176 4177function __param(paramIndex, decorator) { 4178 return function (target, key) { decorator(target, key, paramIndex); } 4179} 4180 4181function __metadata(metadataKey, metadataValue) { 4182 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); 4183} 4184 4185function __awaiter(thisArg, _arguments, P, generator) { 4186 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4187 return new (P || (P = Promise))(function (resolve, reject) { 4188 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 4189 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 4190 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 4191 step((generator = generator.apply(thisArg, _arguments || [])).next()); 4192 });
vendor: 5,103 bytes, lines 4193-4302
4193} 4194 4195function __generator(thisArg, body) { 4196 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 4197 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 4198 function verb(n) { return function (v) { return step([n, v]); }; } 4199 function step(op) { 4200 if (f) throw new TypeError("Generator is already executing."); 4201 while (_) try { 4202 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; 4203 if (y = 0, t) op = [op[0] & 2, t.value]; 4204 switch (op[0]) { 4205 case 0: case 1: t = op; break; 4206 case 4: _.label++; return { value: op[1], done: false }; 4207 case 5: _.label++; y = op[1]; op = [0]; continue; 4208 case 7: op = _.ops.pop(); _.trys.pop(); continue; 4209 default: 4210 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 4211 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 4212 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 4213 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 4214 if (t[2]) _.ops.pop(); 4215 _.trys.pop(); continue; 4216 } 4217 op = body.call(thisArg, _); 4218 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 4219 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 4220 } 4221} 4222 4223var __createBinding = Object.create ? (function(o, m, k, k2) { 4224 if (k2 === undefined) k2 = k; 4225 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); 4226}) : (function(o, m, k, k2) { 4227 if (k2 === undefined) k2 = k; 4228 o[k2] = m[k]; 4229}); 4230 4231function __exportStar(m, o) { 4232 for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p); 4233} 4234 4235function __values(o) { 4236 var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; 4237 if (m) return m.call(o); 4238 if (o && typeof o.length === "number") return { 4239 next: function () { 4240 if (o && i >= o.length) o = void 0; 4241 return { value: o && o[i++], done: !o }; 4242 } 4243 }; 4244 throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); 4245} 4246 4247function __read(o, n) { 4248 var m = typeof Symbol === "function" && o[Symbol.iterator]; 4249 if (!m) return o; 4250 var i = m.call(o), r, ar = [], e; 4251 try { 4252 while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); 4253 } 4254 catch (error) { e = { error: error }; } 4255 finally { 4256 try { 4257 if (r && !r.done && (m = i["return"])) m.call(i); 4258 } 4259 finally { if (e) throw e.error; } 4260 } 4261 return ar; 4262} 4263 4264function __spread() { 4265 for (var ar = [], i = 0; i < arguments.length; i++) 4266 ar = ar.concat(__read(arguments[i])); 4267 return ar; 4268} 4269 4270function __spreadArrays() { 4271 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; 4272 for (var r = Array(s), k = 0, i = 0; i < il; i++) 4273 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) 4274 r[k] = a[j]; 4275 return r; 4276}; 4277 4278function __await(v) { 4279 return this instanceof __await ? (this.v = v, this) : new __await(v); 4280} 4281 4282function __asyncGenerator(thisArg, _arguments, generator) { 4283 if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); 4284 var g = generator.apply(thisArg, _arguments || []), i, q = []; 4285 return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; 4286 function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } 4287 function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } 4288 function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } 4289 function fulfill(value) { resume("next", value); } 4290 function reject(value) { resume("throw", value); } 4291 function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } 4292} 4293 4294function __asyncDelegator(o) { 4295 var i, p; 4296 return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; 4297 function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; } 4298} 4299 4300function __asyncValues(o) { 4301 if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); 4302 var m = o[Symbol.asyncIterator], i;
vendor: 5,690 bytes, lines 4303-4456
4303 return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); 4304 function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } 4305 function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } 4306} 4307 4308function __makeTemplateObject(cooked, raw) { 4309 if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } 4310 return cooked; 4311}; 4312 4313var __setModuleDefault = Object.create ? (function(o, v) { 4314 Object.defineProperty(o, "default", { enumerable: true, value: v }); 4315}) : function(o, v) { 4316 o["default"] = v; 4317}; 4318 4319function __importStar(mod) { 4320 if (mod && mod.__esModule) return mod; 4321 var result = {}; 4322 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 4323 __setModuleDefault(result, mod); 4324 return result; 4325} 4326 4327function __importDefault(mod) { 4328 return (mod && mod.__esModule) ? mod : { default: mod }; 4329} 4330 4331function __classPrivateFieldGet(receiver, privateMap) { 4332 if (!privateMap.has(receiver)) { 4333 throw new TypeError("attempted to get private field on non-instance"); 4334 } 4335 return privateMap.get(receiver); 4336} 4337 4338function __classPrivateFieldSet(receiver, privateMap, value) { 4339 if (!privateMap.has(receiver)) { 4340 throw new TypeError("attempted to set private field on non-instance"); 4341 } 4342 privateMap.set(receiver, value); 4343 return value; 4344} 4345 4346 4347/***/ }), 4348 4349/***/ 4851: 4350/*!******************************************************************!*\ 4351 !*** ./node_modules/@angular/animations/fesm2020/animations.mjs ***! 4352 \******************************************************************/ 4353/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 4354 4355__webpack_require__.r(__webpack_exports__); 4356/* harmony export */ __webpack_require__.d(__webpack_exports__, { 4357/* harmony export */ "AUTO_STYLE": () => (/* binding */ AUTO_STYLE), 4358/* harmony export */ "AnimationBuilder": () => (/* binding */ AnimationBuilder), 4359/* harmony export */ "AnimationFactory": () => (/* binding */ AnimationFactory), 4360/* harmony export */ "NoopAnimationPlayer": () => (/* binding */ NoopAnimationPlayer), 4361/* harmony export */ "animate": () => (/* binding */ animate), 4362/* harmony export */ "animateChild": () => (/* binding */ animateChild), 4363/* harmony export */ "animation": () => (/* binding */ animation), 4364/* harmony export */ "group": () => (/* binding */ group), 4365/* harmony export */ "keyframes": () => (/* binding */ keyframes), 4366/* harmony export */ "query": () => (/* binding */ query), 4367/* harmony export */ "sequence": () => (/* binding */ sequence), 4368/* harmony export */ "stagger": () => (/* binding */ stagger), 4369/* harmony export */ "state": () => (/* binding */ state), 4370/* harmony export */ "style": () => (/* binding */ style), 4371/* harmony export */ "transition": () => (/* binding */ transition), 4372/* harmony export */ "trigger": () => (/* binding */ trigger), 4373/* harmony export */ "useAnimation": () => (/* binding */ useAnimation), 4374/* harmony export */ "ɵAnimationGroupPlayer": () => (/* binding */ AnimationGroupPlayer), 4375/* harmony export */ "ɵPRE_STYLE": () => (/* binding */ ɵPRE_STYLE) 4376/* harmony export */ }); 4377/** 4378 * @license Angular v14.2.10 4379 * (c) 2010-2022 Google LLC. https://angular.io/ 4380 * License: MIT 4381 */ 4382 4383/** 4384 * An injectable service that produces an animation sequence programmatically within an 4385 * Angular component or directive. 4386 * Provided by the `BrowserAnimationsModule` or `NoopAnimationsModule`. 4387 * 4388 * @usageNotes 4389 * 4390 * To use this service, add it to your component or directive as a dependency. 4391 * The service is instantiated along with your component. 4392 * 4393 * Apps do not typically need to create their own animation players, but if you 4394 * do need to, follow these steps: 4395 * 4396 * 1. Use the <code>[AnimationBuilder.build](api/animations/AnimationBuilder#build)()</code> method 4397 * to create a programmatic animation. The method returns an `AnimationFactory` instance. 4398 * 4399 * 2. Use the factory object to create an `AnimationPlayer` and attach it to a DOM element. 4400 * 4401 * 3. Use the player object to control the animation programmatically. 4402 * 4403 * For example: 4404 * 4405 * ```ts 4406 * // import the service from BrowserAnimationsModule 4407 * import {AnimationBuilder} from '@angular/animations'; 4408 * // require the service as a dependency 4409 * class MyCmp { 4410 * constructor(private _builder: AnimationBuilder) {} 4411 * 4412 * makeAnimation(element: any) { 4413 * // first define a reusable animation 4414 * const myAnimation = this._builder.build([ 4415 * style({ width: 0 }), 4416 * animate(1000, style({ width: '100px' })) 4417 * ]); 4418 * 4419 * // use the returned factory object to create a player 4420 * const player = myAnimation.create(element); 4421 * 4422 * player.play(); 4423 * } 4424 * } 4425 * ``` 4426 * 4427 * @publicApi 4428 */ 4429class AnimationBuilder {} 4430/** 4431 * A factory object returned from the 4432 * <code>[AnimationBuilder.build](api/animations/AnimationBuilder#build)()</code> 4433 * method. 4434 * 4435 * @publicApi 4436 */ 4437 4438 4439class AnimationFactory {} 4440/** 4441 * @license 4442 * Copyright Google LLC All Rights Reserved. 4443 * 4444 * Use of this source code is governed by an MIT-style license that can be 4445 * found in the LICENSE file at https://angular.io/license 4446 */ 4447 4448/** 4449 * Specifies automatic styling. 4450 * 4451 * @publicApi 4452 */ 4453 4454 4455const AUTO_STYLE = '*'; 4456/**
4457 * Creates a named animation trigger, containing a list of [`state()`](api/animations/state) 4458 * and `transition()` entries to be evaluated when the expression 4459 * bound to the trigger changes. 4460 * 4461 * @param name An identifying string. 4462 * @param definitions An animation definition object, containing an array of 4463 * [`state()`](api/animations/state) and `transition()` declarations. 4464 * 4465 * @return An object that encapsulates the trigger data. 4466 * 4467 * @usageNotes 4468 * Define an animation trigger in the `animations` section of `@Component` metadata. 4469 * In the template, reference the trigger by name and bind it to a trigger expression that 4470 * evaluates to a defined animation state, using the following format: 4471 * 4472 * `[@triggerName]="expression"` 4473 * 4474 * Animation trigger bindings convert all values to strings, and then match the 4475 * previous and current values against any linked transitions. 4476 * Booleans can be specified as `1` or `true` and `0` or `false`. 4477 * 4478 * ### Usage Example 4479 * 4480 * The following example creates an animation trigger reference based on the provided 4481 * name value. 4482 * The provided animation value is expected to be an array consisting of state and 4483 * transition declarations. 4484 * 4485 * ```typescript 4486 * @Component({ 4487 * selector: "my-component", 4488 * templateUrl: "my-component-tpl.html", 4489 * animations: [ 4490 * trigger("myAnimationTrigger", [ 4491 * state(...), 4492 * state(...), 4493 * transition(...), 4494 * transition(...) 4495 * ]) 4496 * ] 4497 * }) 4498 * class MyComponent { 4499 * myStatusExp = "something"; 4500 * } 4501 * ``` 4502 * 4503 * The template associated with this component makes use of the defined trigger 4504 * by binding to an element within its template code. 4505 * 4506 * ```html 4507 * <!-- somewhere inside of my-component-tpl.html --> 4508 * <div [@myAnimationTrigger]="myStatusExp">...</div> 4509 * ``` 4510 * 4511 * ### Using an inline function 4512 * The `transition` animation method also supports reading an inline function which can decide 4513 * if its associated animation should be run. 4514 * 4515 * ```typescript 4516 * // this method is run each time the `myAnimationTrigger` trigger value changes. 4517 * function myInlineMatcherFn(fromState: string, toState: string, element: any, params: {[key: 4518 string]: any}): boolean { 4519 * // notice that `element` and `params` are also available here 4520 * return toState == 'yes-please-animate'; 4521 * } 4522 * 4523 * @Component({ 4524 * selector: 'my-component', 4525 * templateUrl: 'my-component-tpl.html', 4526 * animations: [ 4527 * trigger('myAnimationTrigger', [ 4528 * transition(myInlineMatcherFn, [ 4529 * // the animation sequence code 4530 * ]), 4531 * ]) 4532 * ] 4533 * }) 4534 * class MyComponent { 4535 * myStatusExp = "yes-please-animate"; 4536 * } 4537 * ``` 4538 * 4539 * ### Disabling Animations 4540 * When true, the special animation control binding `@.disabled` binding prevents 4541 * all animations from rendering. 4542 * Place the `@.disabled` binding on an element to disable 4543 * animations on the element itself, as well as any inner animation triggers 4544 * within the element. 4545 * 4546 * The following example shows how to use this feature: 4547 * 4548 * ```typescript 4549 * @Component({ 4550 * selector: 'my-component', 4551 * template: ` 4552 * <div [@.disabled]="isDisabled"> 4553 * <div [@childAnimation]="exp"></div> 4554 * </div> 4555 * `, 4556 * animations: [ 4557 * trigger("childAnimation", [ 4558 * // ... 4559 * ]) 4560 * ] 4561 * }) 4562 * class MyComponent { 4563 * isDisabled = true; 4564 * exp = '...'; 4565 * } 4566 * ``` 4567 * 4568 * When `@.disabled` is true, it prevents the `@childAnimation` trigger from animating, 4569 * along with any inner animations. 4570 * 4571 * ### Disable animations application-wide 4572 * When an area of the template is set to have animations disabled, 4573 * **all** inner components have their animations disabled as well. 4574 * This means that you can disable all animations for an app 4575 * by placing a host binding set on `@.disabled` on the topmost Angular component. 4576 * 4577 * ```typescript 4578 * import {Component, HostBinding} from '@angular/core'; 4579 * 4580 * @Component({ 4581 * selector: 'app-component', 4582 * templateUrl: 'app.component.html', 4583 * }) 4584 * class AppComponent { 4585 * @HostBinding('@.disabled') 4586 * public animationsDisabled = true; 4587 * } 4588 * ``` 4589 * 4590 * ### Overriding disablement of inner animations 4591 * Despite inner animations being disabled, a parent animation can `query()` 4592 * for inner elements located in disabled areas of the template and still animate 4593 * them if needed. This is also the case for when a sub animation is 4594 * queried by a parent and then later animated using `animateChild()`. 4595 * 4596 * ### Detecting when an animation is disabled
4597 * If a region of the DOM (or the entire application) has its animations disabled, the animation 4598 * trigger callbacks still fire, but for zero seconds. When the callback fires, it provides 4599 * an instance of an `AnimationEvent`. If animations are disabled, 4600 * the `.disabled` flag on the event is true. 4601 * 4602 * @publicApi 4603 */ 4604 4605function trigger(name, definitions) { 4606 return { 4607 type: 7 4608 /* AnimationMetadataType.Trigger */ 4609 , 4610 name, 4611 definitions, 4612 options: {} 4613 }; 4614} 4615/** 4616 * Defines an animation step that combines styling information with timing information. 4617 * 4618 * @param timings Sets `AnimateTimings` for the parent animation. 4619 * A string in the format "duration [delay] [easing]". 4620 * - Duration and delay are expressed as a number and optional time unit, 4621 * such as "1s" or "10ms" for one second and 10 milliseconds, respectively. 4622 * The default unit is milliseconds. 4623 * - The easing value controls how the animation accelerates and decelerates 4624 * during its runtime. Value is one of `ease`, `ease-in`, `ease-out`, 4625 * `ease-in-out`, or a `cubic-bezier()` function call. 4626 * If not supplied, no easing is applied. 4627 * 4628 * For example, the string "1s 100ms ease-out" specifies a duration of 4629 * 1000 milliseconds, and delay of 100 ms, and the "ease-out" easing style, 4630 * which decelerates near the end of the duration. 4631 * @param styles Sets AnimationStyles for the parent animation. 4632 * A function call to either `style()` or `keyframes()` 4633 * that returns a collection of CSS style entries to be applied to the parent animation. 4634 * When null, uses the styles from the destination state. 4635 * This is useful when describing an animation step that will complete an animation; 4636 * see "Animating to the final state" in `transitions()`. 4637 * @returns An object that encapsulates the animation step. 4638 * 4639 * @usageNotes 4640 * Call within an animation `sequence()`, `{@link animations/group group()}`, or 4641 * `transition()` call to specify an animation step 4642 * that applies given style data to the parent animation for a given amount of time. 4643 * 4644 * ### Syntax Examples 4645 * **Timing examples** 4646 * 4647 * The following examples show various `timings` specifications. 4648 * - `animate(500)` : Duration is 500 milliseconds. 4649 * - `animate("1s")` : Duration is 1000 milliseconds. 4650 * - `animate("100ms 0.5s")` : Duration is 100 milliseconds, delay is 500 milliseconds. 4651 * - `animate("5s ease-in")` : Duration is 5000 milliseconds, easing in. 4652 * - `animate("5s 10ms cubic-bezier(.17,.67,.88,.1)")` : Duration is 5000 milliseconds, delay is 10 4653 * milliseconds, easing according to a bezier curve. 4654 * 4655 * **Style examples** 4656 * 4657 * The following example calls `style()` to set a single CSS style. 4658 * ```typescript 4659 * animate(500, style({ background: "red" })) 4660 * ``` 4661 * The following example calls `keyframes()` to set a CSS style 4662 * to different values for successive keyframes. 4663 * ```typescript 4664 * animate(500, keyframes( 4665 * [ 4666 * style({ background: "blue" }), 4667 * style({ background: "red" }) 4668 * ]) 4669 * ``` 4670 * 4671 * @publicApi 4672 */ 4673 4674 4675function animate(timings, styles = null) { 4676 return { 4677 type: 4 4678 /* AnimationMetadataType.Animate */ 4679 , 4680 styles, 4681 timings 4682 }; 4683} 4684/** 4685 * @description Defines a list of animation steps to be run in parallel. 4686 * 4687 * @param steps An array of animation step objects. 4688 * - When steps are defined by `style()` or `animate()` 4689 * function calls, each call within the group is executed instantly. 4690 * - To specify offset styles to be applied at a later time, define steps with 4691 * `keyframes()`, or use `animate()` calls with a delay value. 4692 * For example: 4693 * 4694 * ```typescript 4695 * group([ 4696 * animate("1s", style({ background: "black" })), 4697 * animate("2s", style({ color: "white" })) 4698 * ]) 4699 * ``` 4700 * 4701 * @param options An options object containing a delay and 4702 * developer-defined parameters that provide styling defaults and 4703 * can be overridden on invocation. 4704 * 4705 * @return An object that encapsulates the group data. 4706 * 4707 * @usageNotes 4708 * Grouped animations are useful when a series of styles must be 4709 * animated at different starting times and closed off at different ending times. 4710 * 4711 * When called within a `sequence()` or a 4712 * `transition()` call, does not continue to the next 4713 * instruction until all of the inner animation steps have completed. 4714 * 4715 * @publicApi 4716 */ 4717 4718 4719function group(steps, options = null) { 4720 return { 4721 type: 3
4722 /* AnimationMetadataType.Group */ 4723 , 4724 steps, 4725 options 4726 }; 4727} 4728/** 4729 * Defines a list of animation steps to be run sequentially, one by one. 4730 * 4731 * @param steps An array of animation step objects. 4732 * - Steps defined by `style()` calls apply the styling data immediately. 4733 * - Steps defined by `animate()` calls apply the styling data over time 4734 * as specified by the timing data. 4735 * 4736 * ```typescript 4737 * sequence([ 4738 * style({ opacity: 0 }), 4739 * animate("1s", style({ opacity: 1 })) 4740 * ]) 4741 * ``` 4742 * 4743 * @param options An options object containing a delay and 4744 * developer-defined parameters that provide styling defaults and 4745 * can be overridden on invocation. 4746 * 4747 * @return An object that encapsulates the sequence data. 4748 * 4749 * @usageNotes 4750 * When you pass an array of steps to a 4751 * `transition()` call, the steps run sequentially by default. 4752 * Compare this to the `{@link animations/group group()}` call, which runs animation steps in 4753 *parallel. 4754 * 4755 * When a sequence is used within a `{@link animations/group group()}` or a `transition()` call, 4756 * execution continues to the next instruction only after each of the inner animation 4757 * steps have completed. 4758 * 4759 * @publicApi 4760 **/ 4761 4762 4763function sequence(steps, options = null) { 4764 return { 4765 type: 2 4766 /* AnimationMetadataType.Sequence */ 4767 , 4768 steps, 4769 options 4770 }; 4771} 4772/** 4773 * Declares a key/value object containing CSS properties/styles that 4774 * can then be used for an animation [`state`](api/animations/state), within an animation 4775 *`sequence`, or as styling data for calls to `animate()` and `keyframes()`. 4776 * 4777 * @param tokens A set of CSS styles or HTML styles associated with an animation state. 4778 * The value can be any of the following: 4779 * - A key-value style pair associating a CSS property with a value. 4780 * - An array of key-value style pairs. 4781 * - An asterisk (*), to use auto-styling, where styles are derived from the element 4782 * being animated and applied to the animation when it starts. 4783 * 4784 * Auto-styling can be used to define a state that depends on layout or other 4785 * environmental factors. 4786 * 4787 * @return An object that encapsulates the style data. 4788 * 4789 * @usageNotes 4790 * The following examples create animation styles that collect a set of 4791 * CSS property values: 4792 * 4793 * ```typescript 4794 * // string values for CSS properties 4795 * style({ background: "red", color: "blue" }) 4796 * 4797 * // numerical pixel values 4798 * style({ width: 100, height: 0 }) 4799 * ``` 4800 * 4801 * The following example uses auto-styling to allow an element to animate from 4802 * a height of 0 up to its full height: 4803 * 4804 * ``` 4805 * style({ height: 0 }), 4806 * animate("1s", style({ height: "*" })) 4807 * ``` 4808 * 4809 * @publicApi 4810 **/ 4811 4812 4813function style(tokens) { 4814 return { 4815 type: 6 4816 /* AnimationMetadataType.Style */ 4817 , 4818 styles: tokens, 4819 offset: null 4820 }; 4821} 4822/** 4823 * Declares an animation state within a trigger attached to an element. 4824 * 4825 * @param name One or more names for the defined state in a comma-separated string. 4826 * The following reserved state names can be supplied to define a style for specific use 4827 * cases: 4828 * 4829 * - `void` You can associate styles with this name to be used when 4830 * the element is detached from the application. For example, when an `ngIf` evaluates 4831 * to false, the state of the associated element is void. 4832 * - `*` (asterisk) Indicates the default state. You can associate styles with this name 4833 * to be used as the fallback when the state that is being animated is not declared 4834 * within the trigger. 4835 * 4836 * @param styles A set of CSS styles associated with this state, created using the 4837 * `style()` function. 4838 * This set of styles persists on the element once the state has been reached. 4839 * @param options Parameters that can be passed to the state when it is invoked. 4840 * 0 or more key-value pairs. 4841 * @return An object that encapsulates the new state data. 4842 * 4843 * @usageNotes 4844 * Use the `trigger()` function to register states to an animation trigger. 4845 * Use the `transition()` function to animate between states. 4846 * When a state is active within a component, its associated styles persist on the element, 4847 * even when the animation ends. 4848 * 4849 * @publicApi 4850 **/ 4851 4852 4853function state(name, styles, options) { 4854 return { 4855 type: 0 4856 /* AnimationMetadataType.State */ 4857 , 4858 name, 4859 styles, 4860 options 4861 }; 4862} 4863/** 4864 * Defines a set of animation styles, associating each style with an optional `offset` value. 4865 * 4866 * @param steps A set of animation styles with optional offset data. 4867 * The optional `offset` value for a style specifies a percentage of the total animation 4868 * time at which that style is applied. 4869 * @returns An object that encapsulates the keyframes data. 4870 * 4871 * @usageNotes 4872 * Use with the `animate()` call. Instead of applying animations 4873 * from the current state 4874 * to the destination state, keyframes describe how each style entry is a
4874pplied and at what point 4875 * within the animation arc. 4876 * Compare [CSS Keyframe Animations](https://www.w3schools.com/css/css3_animations.asp). 4877 * 4878 * ### Usage 4879 * 4880 * In the following example, the offset values describe 4881 * when each `backgroundColor` value is applied. The color is red at the start, and changes to 4882 * blue when 20% of the total time has elapsed. 4883 * 4884 * ```typescript 4885 * // the provided offset values 4886 * animate("5s", keyframes([ 4887 * style({ backgroundColor: "red", offset: 0 }), 4888 * style({ backgroundColor: "blue", offset: 0.2 }), 4889 * style({ backgroundColor: "orange", offset: 0.3 }), 4890 * style({ backgroundColor: "black", offset: 1 }) 4891 * ])) 4892 * ``` 4893 * 4894 * If there are no `offset` values specified in the style entries, the offsets 4895 * are calculated automatically. 4896 * 4897 * ```typescript 4898 * animate("5s", keyframes([ 4899 * style({ backgroundColor: "red" }) // offset = 0 4900 * style({ backgroundColor: "blue" }) // offset = 0.33 4901 * style({ backgroundColor: "orange" }) // offset = 0.66 4902 * style({ backgroundColor: "black" }) // offset = 1 4903 * ])) 4904 *``` 4905 4906 * @publicApi 4907 */ 4908 4909 4910function keyframes(steps) { 4911 return { 4912 type: 5 4913 /* AnimationMetadataType.Keyframes */ 4914 , 4915 steps 4916 }; 4917} 4918/** 4919 * Declares an animation transition which is played when a certain specified condition is met. 4920 * 4921 * @param stateChangeExpr A string with a specific format or a function that specifies when the 4922 * animation transition should occur (see [State Change Expression](#state-change-expression)). 4923 * 4924 * @param steps One or more animation objects that represent the animation's instructions. 4925 * 4926 * @param options An options object that can be used to specify a delay for the animation or provide 4927 * custom parameters for it. 4928 * 4929 * @returns An object that encapsulates the transition data. 4930 * 4931 * @usageNotes 4932 * 4933 * ### State Change Expression 4934 * 4935 * The State Change Expression instructs Angular when to run the transition's animations, it can 4936 *either be 4937 * - a string with a specific syntax 4938 * - or a function that compares the previous and current state (value of the expression bound to 4939 * the element's trigger) and returns `true` if the transition should occur or `false` otherwise 4940 * 4941 * The string format can be: 4942 * - `fromState => toState`, which indicates that the transition's animations should occur then the 4943 * expression bound to the trigger's element goes from `fromState` to `toState` 4944 * 4945 * _Example:_ 4946 * ```typescript 4947 * transition('open => closed', animate('.5s ease-out', style({ height: 0 }) )) 4948 * ``` 4949 * 4950 * - `fromState <=> toState`, which indicates that the transition's animations should occur then 4951 * the expression bound to the trigger's element goes from `fromState` to `toState` or vice versa 4952 * 4953 * _Example:_ 4954 * ```typescript 4955 * transition('enabled <=> disabled', animate('1s cubic-bezier(0.8,0.3,0,1)')) 4956 * ``` 4957 * 4958 * - `:enter`/`:leave`, which indicates that the transition's animations should occur when the 4959 * element enters or exists the DOM 4960 * 4961 * _Example:_ 4962 * ```typescript 4963 * transition(':enter', [ 4964 * style({ opacity: 0 }), 4965 * animate('500ms', style({ opacity: 1 })) 4966 * ]) 4967 * ``` 4968 * 4969 * - `:increment`/`:decrement`, which indicates that the transition's animations should occur when 4970 * the numerical expression bound to the trigger's element has increased in value or decreased 4971 * 4972 * _Example:_ 4973 * ```typescript 4974 * transition(':increment', query('@counter', animateChild())) 4975 * ``` 4976 * 4977 * - a sequence of any of the above divided by commas, which indicates that transition's animations 4978 * should occur whenever one of the state change expressions matches 4979 * 4980 * _Example:_ 4981 * ```typescript 4982 * transition(':increment, * => enabled, :enter', animate('1s ease', keyframes([ 4983 * style({ transform: 'scale(1)', offset: 0}), 4984 * style({ transform: 'scale(1.1)', offset: 0.7}), 4985 * style({ transform: 'scale(1)', offset: 1}) 4986 * ]))), 4987 * ``` 4988 * 4989 * Also note that in such context: 4990 * - `void` can be used to indicate the absence of the element 4991 * - asterisks can be used as wildcards that match any state 4992 * - (as a consequence of the above, `void => *` is equivalent to `:enter` and `* => void` is 4993 * equivalent to `:leave`) 4994 * - `true` and `false` also match expression values of `1` and `0` respectively (but do not match 4995 * _truthy_ and _falsy_ values) 4996 * 4997 * <div class="alert is-helpful"> 4998 * 4999 * Be careful about entering end leaving elements as their transitions present a common 5000 * pitfall for developers. 5001 * 5002 * Note that when an element with a trigger enters the DOM its `:enter` transition always 5003 * gets executed, but its `:leave` transition will not be executed if the element is removed 5004 * alongside its parent (as it will be removed "without warning" before its transition has 5005 * a chance to be executed, the only way that such transition can occur is if the element 5006 * is exiting the DOM on its own). 5007 * 5008 * 5009 * </div> 5010 * 5011 * ### Animating to a Final State 5012 * 5013 * If the final step in a transition is a call to `animate()` that uses a timing value
5014 * with no `style` data, that step is automatically considered the final animation arc, 5015 * for the element to reach the final state, in such case Angular automatically adds or removes 5016 * CSS styles to ensure that the element is in the correct final state. 5017 * 5018 * 5019 * ### Usage Examples 5020 * 5021 * - Transition animations applied based on 5022 * the trigger's expression value 5023 * 5024 * ```HTML 5025 * <div [@myAnimationTrigger]="myStatusExp"> 5026 * ... 5027 * </div> 5028 * ``` 5029 * 5030 * ```typescript 5031 * trigger("myAnimationTrigger", [ 5032 * ..., // states 5033 * transition("on => off, open => closed", animate(500)), 5034 * transition("* <=> error", query('.indicator', animateChild())) 5035 * ]) 5036 * ``` 5037 * 5038 * - Transition animations applied based on custom logic dependent 5039 * on the trigger's expression value and provided parameters 5040 * 5041 * ```HTML 5042 * <div [@myAnimationTrigger]="{ 5043 * value: stepName, 5044 * params: { target: currentTarget } 5045 * }"> 5046 * ... 5047 * </div> 5048 * ``` 5049 * 5050 * ```typescript 5051 * trigger("myAnimationTrigger", [ 5052 * ..., // states 5053 * transition( 5054 * (fromState, toState, _element, params) => 5055 * ['firststep', 'laststep'].includes(fromState.toLowerCase()) 5056 * && toState === params?.['target'], 5057 * animate('1s') 5058 * ) 5059 * ]) 5060 * ``` 5061 * 5062 * @publicApi 5063 **/ 5064 5065 5066function transition(stateChangeExpr, steps, options = null) { 5067 return { 5068 type: 1 5069 /* AnimationMetadataType.Transition */ 5070 , 5071 expr: stateChangeExpr, 5072 animation: steps, 5073 options 5074 }; 5075} 5076/** 5077 * Produces a reusable animation that can be invoked in another animation or sequence, 5078 * by calling the `useAnimation()` function. 5079 * 5080 * @param steps One or more animation objects, as returned by the `animate()` 5081 * or `sequence()` function, that form a transformation from one state to another. 5082 * A sequence is used by default when you pass an array. 5083 * @param options An options object that can contain a delay value for the start of the 5084 * animation, and additional developer-defined parameters. 5085 * Provided values for additional parameters are used as defaults, 5086 * and override values can be passed to the caller on invocation. 5087 * @returns An object that encapsulates the animation data. 5088 * 5089 * @usageNotes 5090 * The following example defines a reusable animation, providing some default parameter 5091 * values. 5092 * 5093 * ```typescript 5094 * var fadeAnimation = animation([ 5095 * style({ opacity: '{{ start }}' }), 5096 * animate('{{ time }}', 5097 * style({ opacity: '{{ end }}'})) 5098 * ], 5099 * { params: { time: '1000ms', start: 0, end: 1 }}); 5100 * ``` 5101 * 5102 * The following invokes the defined animation with a call to `useAnimation()`, 5103 * passing in override parameter values. 5104 * 5105 * ```js 5106 * useAnimation(fadeAnimation, { 5107 * params: { 5108 * time: '2s', 5109 * start: 1, 5110 * end: 0 5111 * } 5112 * }) 5113 * ``` 5114 * 5115 * If any of the passed-in parameter values are missing from this call, 5116 * the default values are used. If one or more parameter values are missing before a step is 5117 * animated, `useAnimation()` throws an error. 5118 * 5119 * @publicApi 5120 */ 5121 5122 5123function animation(steps, options = null) { 5124 return { 5125 type: 8 5126 /* AnimationMetadataType.Reference */ 5127 , 5128 animation: steps, 5129 options 5130 }; 5131} 5132/** 5133 * Executes a queried inner animation element within an animation sequence. 5134 * 5135 * @param options An options object that can contain a delay value for the start of the 5136 * animation, and additional override values for developer-defined parameters. 5137 * @return An object that encapsulates the child animation data. 5138 * 5139 * @usageNotes 5140 * Each time an animation is triggered in Angular, the parent animation 5141 * has priority and any child animations are blocked. In order 5142 * for a child animation to run, the parent animation must query each of the elements 5143 * containing child animations, and run them using this function. 5144 * 5145 * Note that this feature is designed to be used with `query()` and it will only work 5146 * with animations that are assigned using the Angular animation library. CSS keyframes 5147 * and transitions are not handled by this API. 5148 * 5149 * @publicApi 5150 */ 5151 5152 5153function animateChild(options = null) { 5154 return { 5155 type: 9 5156 /* AnimationMetadataType.AnimateChild */ 5157 , 5158 options 5159 }; 5160} 5161/** 5162 * Starts a reusable animation that is created using the `animation()` function. 5163 * 5164 * @param animation The reusable animation to start. 5165 * @param options An options object that can contain a delay value for the start of 5166 * the animation, and additional override values for developer-defined parameters. 5167 * @return An object that contains the animation parameters. 5168 * 5169 * @publicApi 5170 */ 5171 5172 5173function useAnimation(animation, options = null) { 5174 return { 5175 type: 10 5176 /* AnimationMetadataType.AnimateRef */ 5177 , 5178 animation, 5179 options 5180 }; 5181} 5182/** 5183 * Finds one or more inner elements within the current element that is 5184 * being animated within a sequence. Use with `animate()`. 5185 * 5186 * @param selector The element to query, or a set of elements that contain Angular-specific 5187 * characteristics, specified with one or more of the following tokens. 5188 * - `query(":enter")` or `query(":leave")` : Query for newly inserted/removed elements (not 5189 * all elements can be queried via these tokens, see 5190 * [Entering and Leaving Elements](#entering-and-leaving-elements)) 5191 * - `query(":animating")` : Query all currently animating elements. 5192 * - `query("@triggerName")` : Query elements that contain an animation trigger. 5193 * - `query("@*")` : Query all elements that contain an animation triggers. 5194 * - `query(":self")` : Include the current element into the animation sequence. 5195 * 5196 * @param animation One or more animation steps to apply to the queried element or elements. 5197 * An array is treated as an animation sequence. 5198 * @param options An options object. Use the 'limit' field to limit the total number of 5199 * items to collect. 5200 * @return An object that encapsulates the query data. 5201 * 5202 * @usageNotes 5203 * 5204 * ### Multiple Tokens 5205 * 5206 * Tokens can be merged into a combined query selector string. For example: 5207 * 5208 * ```typescript
5209 * query(':self, .record:enter, .record:leave, @subTrigger', [...]) 5210 * ``` 5211 * 5212 * The `query()` function collects multiple elements and works internally by using 5213 * `element.querySelectorAll`. Use the `limit` field of an options object to limit 5214 * the total number of items to be collected. For example: 5215 * 5216 * ```js 5217 * query('div', [ 5218 * animate(...), 5219 * animate(...) 5220 * ], { limit: 1 }) 5221 * ``` 5222 * 5223 * By default, throws an error when zero items are found. Set the 5224 * `optional` flag to ignore this error. For example: 5225 * 5226 * ```js 5227 * query('.some-element-that-may-not-be-there', [ 5228 * animate(...), 5229 * animate(...) 5230 * ], { optional: true }) 5231 * ``` 5232 * 5233 * ### Entering and Leaving Elements 5234 * 5235 * Not all elements can be queried via the `:enter` and `:leave` tokens, the only ones 5236 * that can are those that Angular assumes can enter/leave based on their own logic 5237 * (if their insertion/removal is simply a consequence of that of their parent they 5238 * should be queried via a different token in their parent's `:enter`/`:leave` transitions). 5239 * 5240 * The only elements Angular assumes can enter/leave based on their own logic (thus the only 5241 * ones that can be queried via the `:enter` and `:leave` tokens) are: 5242 * - Those inserted dynamically (via `ViewContainerRef`) 5243 * - Those that have a structural directive (which, under the hood, are a subset of the above ones) 5244 * 5245 * <div class="alert is-helpful"> 5246 * 5247 * Note that elements will be successfully queried via `:enter`/`:leave` even if their 5248 * insertion/removal is not done manually via `ViewContainerRef`or caused by their structural 5249 * directive (e.g. they enter/exit alongside their parent). 5250 * 5251 * </div> 5252 * 5253 * <div class="alert is-important"> 5254 * 5255 * There is an exception to what previously mentioned, besides elements entering/leaving based on 5256 * their own logic, elements with an animation trigger can always be queried via `:leave` when 5257 * their parent is also leaving. 5258 * 5259 * </div> 5260 * 5261 * ### Usage Example 5262 * 5263 * The following example queries for inner elements and animates them 5264 * individually using `animate()`. 5265 * 5266 * ```typescript 5267 * @Component({ 5268 * selector: 'inner', 5269 * template: ` 5270 * <div [@queryAnimation]="exp"> 5271 * <h1>Title</h1> 5272 * <div class="content"> 5273 * Blah blah blah 5274 * </div> 5275 * </div> 5276 * `, 5277 * animations: [ 5278 * trigger('queryAnimation', [ 5279 * transition('* => goAnimate', [ 5280 * // hide the inner elements 5281 * query('h1', style({ opacity: 0 })), 5282 * query('.content', style({ opacity: 0 })), 5283 * 5284 * // animate the inner elements in, one by one 5285 * query('h1', animate(1000, style({ opacity: 1 }))), 5286 * query('.content', animate(1000, style({ opacity: 1 }))), 5287 * ]) 5288 * ]) 5289 * ] 5290 * }) 5291 * class Cmp { 5292 * exp = ''; 5293 * 5294 * goAnimate() { 5295 * this.exp = 'goAnimate'; 5296 * } 5297 * } 5298 * ``` 5299 * 5300 * @publicApi 5301 */ 5302 5303 5304function query(selector, animation, options = null) { 5305 return { 5306 type: 11 5307 /* AnimationMetadataType.Query */ 5308 , 5309 selector, 5310 animation, 5311 options 5312 }; 5313} 5314/** 5315 * Use within an animation `query()` call to issue a timing gap after 5316 * each queried item is animated. 5317 * 5318 * @param timings A delay value. 5319 * @param animation One ore more animation steps. 5320 * @returns An object that encapsulates the stagger data. 5321 * 5322 * @usageNotes 5323 * In the following example, a container element wraps a list of items stamped out 5324 * by an `ngFor`. The container element contains an animation trigger that will later be set 5325 * to query for each of the inner items. 5326 * 5327 * Each time items are added, the opacity fade-in animation runs, 5328 * and each removed item is faded out. 5329 * When either of these animations occur, the stagger effect is 5330 * applied after each item's animation is started. 5331 * 5332 * ```html 5333 * <!-- list.component.html --> 5334 * <button (click)="toggle()">Show / Hide Items</button> 5335 * <hr /> 5336 * <div [@listAnimation]="items.length"> 5337 * <div *ngFor="let item of items"> 5338 * {{ item }} 5339 * </div> 5340 * </div> 5341 * ``` 5342 * 5343 * Here is the component code: 5344 * 5345 * ```typescript 5346 * import {trigger, transition, style, animate, query, stagger} from '@angular/animations'; 5347 * @Component({ 5348 * templateUrl: 'list.component.html', 5349 * animations: [ 5350 * trigger('listAnimation', [ 5351 * ... 5352 * ]) 5353 * ] 5354 * }) 5355 * class ListComponent { 5356 * items = []; 5357 * 5358 * showItems() { 5359 * this.items = [0,1,2,3,4]; 5360 * } 5361 * 5362 * hideItems() { 5363 * this.items = []; 5364 * } 5365 * 5366 * toggle() { 5367 * this.items.length ? this.hideItems() : this.showItems(); 5368 * } 5369 * } 5370 * ``` 5371 * 5372 * Here is the animation trigger code: 5373 * 5374 * ```typescript 5375 * trigger('listAnimation', [ 5376 * transition('* => *', [ // each time the binding value changes 5377 * query(':leave', [ 5378 * stagger(100, [
5379 * animate('0.5s', style({ opacity: 0 })) 5380 * ]) 5381 * ]), 5382 * query(':enter', [ 5383 * style({ opacity: 0 }), 5384 * stagger(100, [ 5385 * animate('0.5s', style({ opacity: 1 })) 5386 * ]) 5387 * ]) 5388 * ]) 5389 * ]) 5390 * ``` 5391 * 5392 * @publicApi 5393 */ 5394 5395 5396function stagger(timings, animation) { 5397 return { 5398 type: 12 5399 /* AnimationMetadataType.Stagger */ 5400 , 5401 timings, 5402 animation 5403 }; 5404} 5405/** 5406 * @license 5407 * Copyright Google LLC All Rights Reserved. 5408 * 5409 * Use of this source code is governed by an MIT-style license that can be 5410 * found in the LICENSE file at https://angular.io/license 5411 */ 5412 5413 5414function scheduleMicroTask(cb) { 5415 Promise.resolve().then(cb); 5416} 5417/** 5418 * @license 5419 * Copyright Google LLC All Rights Reserved. 5420 * 5421 * Use of this source code is governed by an MIT-style license that can be 5422 * found in the LICENSE file at https://angular.io/license 5423 */ 5424 5425/** 5426 * An empty programmatic controller for reusable animations. 5427 * Used internally when animations are disabled, to avoid 5428 * checking for the null case when an animation player is expected. 5429 * 5430 * @see `animate()` 5431 * @see `AnimationPlayer` 5432 * @see `GroupPlayer` 5433 * 5434 * @publicApi 5435 */ 5436 5437 5438class NoopAnimationPlayer { 5439 constructor(duration = 0, delay = 0) { 5440 this._onDoneFns = []; 5441 this._onStartFns = []; 5442 this._onDestroyFns = []; 5443 this._originalOnDoneFns = []; 5444 this._originalOnStartFns = []; 5445 this._started = false; 5446 this._destroyed = false; 5447 this._finished = false; 5448 this._position = 0; 5449 this.parentPlayer = null; 5450 this.totalTime = duration + delay; 5451 } 5452 5453 _onFinish() { 5454 if (!this._finished) { 5455 this._finished = true; 5456 5457 this._onDoneFns.forEach(fn => fn()); 5458 5459 this._onDoneFns = []; 5460 } 5461 } 5462 5463 onStart(fn) { 5464 this._originalOnStartFns.push(fn); 5465 5466 this._onStartFns.push(fn); 5467 } 5468 5469 onDone(fn) { 5470 this._originalOnDoneFns.push(fn); 5471 5472 this._onDoneFns.push(fn); 5473 } 5474 5475 onDestroy(fn) { 5476 this._onDestroyFns.push(fn); 5477 } 5478 5479 hasStarted() { 5480 return this._started; 5481 } 5482 5483 init() {} 5484 5485 play() { 5486 if (!this.hasStarted()) { 5487 this._onStart(); 5488 5489 this.triggerMicrotask(); 5490 } 5491 5492 this._started = true; 5493 } 5494 /** @internal */ 5495 5496 5497 triggerMicrotask() { 5498 scheduleMicroTask(() => this._onFinish()); 5499 } 5500 5501 _onStart() { 5502 this._onStartFns.forEach(fn => fn()); 5503 5504 this._onStartFns = []; 5505 } 5506 5507 pause() {} 5508 5509 restart() {} 5510 5511 finish() { 5512 this._onFinish(); 5513 } 5514 5515 destroy() { 5516 if (!this._destroyed) { 5517 this._destroyed = true; 5518 5519 if (!this.hasStarted()) { 5520 this._onStart(); 5521 } 5522 5523 this.finish(); 5524 5525 this._onDestroyFns.forEach(fn => fn()); 5526 5527 this._onDestroyFns = []; 5528 } 5529 } 5530 5531 reset() { 5532 this._started = false; 5533 this._finished = false; 5534 this._onStartFns = this._originalOnStartFns; 5535 this._onDoneFns = this._originalOnDoneFns; 5536 } 5537 5538 setPosition(position) { 5539 this._position = this.totalTime ? position * this.totalTime : 1; 5540 } 5541 5542 getPosition() { 5543 return this.totalTime ? this._position / this.totalTime : 1; 5544 } 5545 /** @internal */ 5546 5547 5548 triggerCallback(phaseName) { 5549 const methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns; 5550 methods.forEach(fn => fn()); 5551 methods.length = 0; 5552 } 5553 5554} 5555/** 5556 * @license 5557 * Copyright Google LLC All Rights Reserved. 5558 * 5559 * Use of this source code is governed by an MIT-style license that can be 5560 * found in the LICENSE file at https://angular.io/license 5561 */ 5562 5563/** 5564 * A programmatic controller for a group of reusable animations. 5565 * Used internally to control animations. 5566 * 5567 * @see `AnimationPlayer` 5568 * @see `{@link animations/group group()}` 5569 * 5570 */ 5571 5572 5573class AnimationGroupPlayer { 5574 constructor(_players) { 5575 this._onDoneFns = []; 5576 this._onStartFns = []; 5577 this._finished = false; 5578 this._started = false; 5579 this._destroyed = false; 5580 this._onDestroyFns = []; 5581 this.parentPlayer = null; 5582 this.totalTime = 0; 5583 this.players = _players; 5584 let doneCount = 0; 5585 let destroyCount = 0; 5586 let startCount = 0; 5587 const total = this.players.length; 5588 5589 if (total == 0) { 5590 scheduleMicroTask(() => this._onFinish()); 5591 } else {
5592 this.players.forEach(player => { 5593 player.onDone(() => { 5594 if (++doneCount == total) { 5595 this._onFinish(); 5596 } 5597 }); 5598 player.onDestroy(() => { 5599 if (++destroyCount == total) { 5600 this._onDestroy(); 5601 } 5602 }); 5603 player.onStart(() => { 5604 if (++startCount == total) { 5605 this._onStart(); 5606 } 5607 }); 5608 }); 5609 } 5610 5611 this.totalTime = this.players.reduce((time, player) => Math.max(time, player.totalTime), 0); 5612 } 5613 5614 _onFinish() { 5615 if (!this._finished) { 5616 this._finished = true; 5617 5618 this._onDoneFns.forEach(fn => fn()); 5619 5620 this._onDoneFns = []; 5621 } 5622 } 5623 5624 init() { 5625 this.players.forEach(player => player.init()); 5626 } 5627 5628 onStart(fn) { 5629 this._onStartFns.push(fn); 5630 } 5631 5632 _onStart() { 5633 if (!this.hasStarted()) { 5634 this._started = true; 5635 5636 this._onStartFns.forEach(fn => fn()); 5637 5638 this._onStartFns = []; 5639 } 5640 } 5641 5642 onDone(fn) { 5643 this._onDoneFns.push(fn); 5644 } 5645 5646 onDestroy(fn) { 5647 this._onDestroyFns.push(fn); 5648 } 5649 5650 hasStarted() { 5651 return this._started; 5652 } 5653 5654 play() { 5655 if (!this.parentPlayer) { 5656 this.init(); 5657 } 5658 5659 this._onStart(); 5660 5661 this.players.forEach(player => player.play()); 5662 } 5663 5664 pause() { 5665 this.players.forEach(player => player.pause()); 5666 } 5667 5668 restart() { 5669 this.players.forEach(player => player.restart()); 5670 } 5671 5672 finish() { 5673 this._onFinish(); 5674 5675 this.players.forEach(player => player.finish()); 5676 } 5677 5678 destroy() { 5679 this._onDestroy(); 5680 } 5681 5682 _onDestroy() { 5683 if (!this._destroyed) { 5684 this._destroyed = true; 5685 5686 this._onFinish(); 5687 5688 this.players.forEach(player => player.destroy()); 5689 5690 this._onDestroyFns.forEach(fn => fn()); 5691 5692 this._onDestroyFns = []; 5693 } 5694 } 5695 5696 reset() { 5697 this.players.forEach(player => player.reset()); 5698 this._destroyed = false; 5699 this._finished = false; 5700 this._started = false; 5701 } 5702 5703 setPosition(p) { 5704 const timeAtPosition = p * this.totalTime; 5705 this.players.forEach(player => { 5706 const position = player.totalTime ? Math.min(1, timeAtPosition / player.totalTime) : 1; 5707 player.setPosition(position); 5708 }); 5709 } 5710 5711 getPosition() { 5712 const longestPlayer = this.players.reduce((longestSoFar, player) => { 5713 const newPlayerIsLongest = longestSoFar === null || player.totalTime > longestSoFar.totalTime; 5714 return newPlayerIsLongest ? player : longestSoFar; 5715 }, null); 5716 return longestPlayer != null ? longestPlayer.getPosition() : 0; 5717 } 5718 5719 beforeDestroy() { 5720 this.players.forEach(player => { 5721 if (player.beforeDestroy) { 5722 player.beforeDestroy(); 5723 } 5724 }); 5725 } 5726 /** @internal */ 5727 5728 5729 triggerCallback(phaseName) { 5730 const methods = phaseName == 'start' ? this._onStartFns : this._onDoneFns; 5731 methods.forEach(fn => fn()); 5732 methods.length = 0; 5733 } 5734 5735} 5736/** 5737 * @license 5738 * Copyright Google LLC All Rights Reserved. 5739 * 5740 * Use of this source code is governed by an MIT-style license that can be 5741 * found in the LICENSE file at https://angular.io/license 5742 */ 5743 5744 5745const ɵPRE_STYLE = '!'; 5746/** 5747 * @license 5748 * Copyright Google LLC All Rights Reserved. 5749 * 5750 * Use of this source code is governed by an MIT-style license that can be 5751 * found in the LICENSE file at https://angular.io/license 5752 */ 5753 5754/** 5755 * @license 5756 * Copyright Google LLC All Rights Reserved. 5757 * 5758 * Use of this source code is governed by an MIT-style license that can be 5759 * found in the LICENSE file at https://angular.io/license 5760 */ 5761 5762/** 5763 * @license 5764 * Copyright Google LLC All Rights Reserved. 5765 * 5766 * Use of this source code is governed by an MIT-style license that can be 5767 * found in the LICENSE file at https://angular.io/license 5768 */ 5769 5770/** 5771 * Generated bundle index. Do not edit. 5772 */ 5773 5774 5775 5776/***/ }), 5777 5778/***/ 5787: 5779/*!***************************************************************!*\ 5780 !*** ./node_modules/@angular/animations/fesm2020/browser.mjs ***! 5781 \***************************************************************/ 5782/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 5783 5784__webpack_require__.r(__webpack_exports__); 5785/* harmony export */ __webpack_require__.d(__webpack_exports__, { 5786/* harmony export */ "AnimationDriver": () => (/* binding */ AnimationDriver), 5787/* harmony export */ "ɵAnimation": () => (/* binding */ Animation), 5788/* harmony export */ "ɵAnimationEngine": () => (/* binding */ AnimationEngine), 5789/* harmony export */ "ɵAnimationStyleNormalizer": () => (/* binding */ AnimationStyleNormalizer), 5790/* harmony export */ "ɵNoopAnimationDriver": () => (/* binding */ NoopAnimationDriver), 5791/* harmony export */ "ɵNoopAnimationStyleNormalizer": () => (/* binding */ NoopAnimationStyleNormalizer), 5792/* harmony export */ "ɵWebAnimationsDriver": () => (/* binding */ WebAnimationsDriver), 5793/* harmony export */ "ɵWebAnimationsPlayer": () => (/* binding */ WebAnimationsPlayer), 5794/* harmony export */ "ɵWebAnimationsStyleNormalizer": () => (/* binding */ WebAnimationsStyleNormalizer), 5795/* harmony export */ "ɵallowPreviousPlayerStylesMerge": () => (/* binding */ allowPreviousPlayerStylesMerge), 5796/* harmony export */ "ɵcontainsElement": () => (/* binding */ containsElement), 5797/* harmony export */ "ɵgetParentElement": () => (/* binding */ getParentElement), 5798/* harmony export */ "ɵinvokeQuery": () => (/* binding */ invokeQuery), 5799/* harmony export */ "ɵnormalizeKeyframes": () => (/* binding */ normalizeKeyframes), 5800/* harmony export */ "ɵvalidateStyleProperty": () => (/* binding */ validateStyleProperty) 5801/* harmony export */ }); 5802/* harmony import */ var _angular_animations__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/animations */ 4851); 5803/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 2560); 5804/** 5805 * @license Angular v14.2.10 5806 * (c) 2010-2022 Google LLC. https://angular.io/ 5807 * License: MIT 5808 */ 5809 5810 5811 5812/** 5813 * @license 5814 * Copyright Google LLC All Rights Reserved. 5815 * 5816 * Use of this source code is governed by an MIT-style license that can be 5817 * found in the LICENSE file at https://angular.io/license 5818 */ 5819 5820const LINE_START = '\n - '; 5821
5822function invalidTimingValue(exp) { 5823 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3000 5824 /* RuntimeErrorCode.INVALID_TIMING_VALUE */ 5825 , ngDevMode && `The provided timing value "${exp}" is invalid.`); 5826} 5827 5828function negativeStepValue() { 5829 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3100 5830 /* RuntimeErrorCode.NEGATIVE_STEP_VALUE */ 5831 , ngDevMode && 'Duration values below 0 are not allowed for this animation step.'); 5832} 5833 5834function negativeDelayValue() { 5835 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3101 5836 /* RuntimeErrorCode.NEGATIVE_DELAY_VALUE */ 5837 , ngDevMode && 'Delay values below 0 are not allowed for this animation step.'); 5838} 5839 5840function invalidStyleParams(varName) { 5841 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3001 5842 /* RuntimeErrorCode.INVALID_STYLE_PARAMS */ 5843 , ngDevMode && `Unable to resolve the local animation param ${varName} in the given list of values`); 5844} 5845 5846function invalidParamValue(varName) { 5847 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3003 5848 /* RuntimeErrorCode.INVALID_PARAM_VALUE */ 5849 , ngDevMode && `Please provide a value for the animation param ${varName}`); 5850} 5851
5852function invalidNodeType(nodeType) { 5853 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3004 5854 /* RuntimeErrorCode.INVALID_NODE_TYPE */ 5855 , ngDevMode && `Unable to resolve animation metadata node #${nodeType}`); 5856} 5857 5858function invalidCssUnitValue(userProvidedProperty, value) { 5859 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3005 5860 /* RuntimeErrorCode.INVALID_CSS_UNIT_VALUE */ 5861 , ngDevMode && `Please provide a CSS unit value for ${userProvidedProperty}:${value}`); 5862} 5863 5864function invalidTrigger() { 5865 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3006 5866 /* RuntimeErrorCode.INVALID_TRIGGER */ 5867 , ngDevMode && 'animation triggers cannot be prefixed with an `@` sign (e.g. trigger(\'@foo\', [...]))'); 5868} 5869 5870function invalidDefinition() { 5871 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3007 5872 /* RuntimeErrorCode.INVALID_DEFINITION */ 5873 , ngDevMode && 'only state() and transition() definitions can sit inside of a trigger()'); 5874} 5875
5876function invalidState(metadataName, missingSubs) { 5877 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3008 5878 /* RuntimeErrorCode.INVALID_STATE */ 5879 , ngDevMode && `state("${metadataName}", ...) must define default values for all the following style substitutions: ${missingSubs.join(', ')}`); 5880} 5881 5882function invalidStyleValue(value) { 5883 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3002 5884 /* RuntimeErrorCode.INVALID_STYLE_VALUE */ 5885 , ngDevMode && `The provided style string value ${value} is not allowed.`); 5886} 5887 5888function invalidProperty(prop) { 5889 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3009 5890 /* RuntimeErrorCode.INVALID_PROPERTY */ 5891 , ngDevMode && `The provided animation property "${prop}" is not a supported CSS property for animations`); 5892} 5893 5894function invalidParallelAnimation(prop, firstStart, firstEnd, secondStart, secondEnd) { 5895 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3010 5896 /* RuntimeErrorCode.INVALID_PARALLEL_ANIMATION */ 5897 , ngDevMode && `The CSS property "${prop}" that exists between the times of "${firstStart}ms" and "${firstEnd}ms" is also being animated in a parallel animation between the times of "${secondStart}ms" and "${secondEnd}ms"`); 5898} 5899
5900function invalidKeyframes() { 5901 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3011 5902 /* RuntimeErrorCode.INVALID_KEYFRAMES */ 5903 , ngDevMode && `keyframes() must be placed inside of a call to animate()`); 5904} 5905 5906function invalidOffset() { 5907 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3012 5908 /* RuntimeErrorCode.INVALID_OFFSET */ 5909 , ngDevMode && `Please ensure that all keyframe offsets are between 0 and 1`); 5910} 5911 5912function keyframeOffsetsOutOfOrder() { 5913 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3200 5914 /* RuntimeErrorCode.KEYFRAME_OFFSETS_OUT_OF_ORDER */ 5915 , ngDevMode && `Please ensure that all keyframe offsets are in order`); 5916} 5917 5918function keyframesMissingOffsets() { 5919 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3202 5920 /* RuntimeErrorCode.KEYFRAMES_MISSING_OFFSETS */ 5921 , ngDevMode && `Not all style() steps within the declared keyframes() contain offsets`); 5922} 5923 5924function invalidStagger() { 5925 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3013 5926 /* RuntimeErrorCode.INVALID_STAGGER */ 5927 , ngDevMode && `stagger() can only be used inside of query()`); 5928} 5929
5930function invalidQuery(selector) { 5931 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3014 5932 /* RuntimeErrorCode.INVALID_QUERY */ 5933 , ngDevMode && `\`query("${selector}")\` returned zero elements. (Use \`query("${selector}", { optional: true })\` if you wish to allow this.)`); 5934} 5935 5936function invalidExpression(expr) { 5937 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3015 5938 /* RuntimeErrorCode.INVALID_EXPRESSION */ 5939 , ngDevMode && `The provided transition expression "${expr}" is not supported`); 5940} 5941 5942function invalidTransitionAlias(alias) { 5943 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3016 5944 /* RuntimeErrorCode.INVALID_TRANSITION_ALIAS */ 5945 , ngDevMode && `The transition alias value "${alias}" is not supported`); 5946} 5947 5948function validationFailed(errors) { 5949 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3500 5950 /* RuntimeErrorCode.VALIDATION_FAILED */ 5951 , ngDevMode && `animation validation failed:\n${errors.map(err => err.message).join('\n')}`); 5952} 5953 5954function buildingFailed(errors) { 5955 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3501 5956 /* RuntimeErrorCode.BUILDING_FAILED */ 5957 , ngDevMode && `animation building failed:\n${errors.map(err => err.message).join('\n')}`); 5958} 5959 5960function triggerBuildFailed(name, errors) { 5961 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3404 5962 /* RuntimeErrorCode.TRIGGER_BUILD_FAILED */ 5963 , ngDevMode && `The animation trigger "${name}" has failed to build due to the following errors:\n - ${errors.map(err => err.message).join('\n - ')}`); 5964} 5965 5966function animationFailed(errors) { 5967 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3502 5968 /* RuntimeErrorCode.ANIMATION_FAILED */ 5969 , ngDevMode && `Unable to animate due to the following errors:${LINE_START}${errors.map(err => err.message).join(LINE_START)}`); 5970} 5971 5972function registerFailed(errors) { 5973 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3503 5974 /* RuntimeErrorCode.REGISTRATION_FAILED */ 5975 , ngDevMode && `Unable to build the animation due to the following errors: ${errors.map(err => err.message).join('\n')}`); 5976} 5977 5978function missingOrDestroyedAnimation() { 5979 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3300 5980 /* RuntimeErrorCode.MISSING_OR_DESTROYED_ANIMATION */ 5981 , ngDevMode && 'The requested animation doesn\'t exist or has already been destroyed'); 5982} 5983 5984function createAnimationFailed(errors) { 5985 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3504 5986 /* RuntimeErrorCode.CREATE_ANIMATION_FAILED */ 5987 , ngDevMode && `Unable to create the animation due to the following errors:${errors.map(err => err.message).join('\n')}`); 5988} 5989 5990function missingPlayer(id) { 5991 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3301 5992 /* RuntimeErrorCode.MISSING_PLAYER */ 5993 , ngDevMode && `Unable to find the timeline player referenced by ${id}`); 5994} 5995 5996function missingTrigger(phase, name) { 5997 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3302 5998 /* RuntimeErrorCode.MISSING_TRIGGER */ 5999 , ngDevMode && `Unable to listen on the animation trigger event "${phase}" because the animation trigger "${name}" doesn\'t exist!`); 6000} 6001 6002function missingEvent(name) { 6003 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3303 6004 /* RuntimeErrorCode.MISSING_EVENT */ 6005 , ngDevMode && `Unable to listen on the animation trigger "${name}" because the provided event is undefined!`); 6006} 6007 6008function unsupportedTriggerEvent(phase, name) { 6009 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3400 6010 /* RuntimeErrorCode.UNSUPPORTED_TRIGGER_EVENT */ 6011 , ngDevMode && `The provided animation trigger event "${phase}" for the animation trigger "${name}" is not supported!`); 6012} 6013 6014function unregisteredTrigger(name) { 6015 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3401 6016 /* RuntimeErrorCode.UNREGISTERED_TRIGGER */ 6017 , ngDevMode && `The provided animation trigger "${name}" has not been registered!`); 6018} 6019 6020function triggerTransitionsFailed(errors) { 6021 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3402 6022 /* RuntimeErrorCode.TRIGGER_TRANSITIONS_FAILED */ 6023 , ngDevMode && `Unable to process animations due to the following failed trigger transitions\n ${errors.map(err => err.message).join('\n')}`); 6024} 6025 6026function triggerParsingFailed(name, errors) { 6027 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3403 6028 /* RuntimeErrorCode.TRIGGER_PARSING_FAILED */ 6029 , ngDevMode && `Animation parsing for the ${name} trigger have failed:${LINE_START}${errors.map(err => err.message).join(LINE_START)}`); 6030} 6031 6032function transitionFailed(name, errors) { 6033 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](3505 6034 /* RuntimeErrorCode.TRANSITION_FAILED */ 6035 , ngDevMode && `@${name} has failed due to:\n ${errors.map(err => err.message).join('\n- ')}`); 6036} 6037/** 6038 * @license 6039 * Copyright Google LLC All Rights Reserved. 6040 * 6041 * Use of this source code is governed by an MIT-style license that can be 6042 * found in the LICENSE file at https://angular.io/license 6043 */ 6044 6045/** 6046 * Set of all animatable CSS properties 6047 * 6048 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties 6049 */ 6050 6051 6052const ANIMATABLE_PROP_SET = new Set(['-moz-outline-radius', '-moz-outline-radius-bottomleft', '-moz-outline-radius-bottomright', '-moz-outline-radius-topleft', '-moz-outline-radius-topright', '-ms-grid-columns', '-ms-grid-rows', '-webkit-line-clamp', '-webkit-text-fill-color', '-webkit-text-stroke', '-webkit-text-stroke-color', 'accent-color', 'all', 'backdrop-filter', 'background', 'background-color', 'background-position', 'background-size', 'block-size', 'border', 'border-block-end', 'border-block-end-color', 'border-block-end-width', 'border-block-start', 'border-block-start-color', 'border-block-start-width', 'border-bottom', 'border-bottom-color', 'border-bottom-left-radius', 'border-bottom-right-radius', 'border-bottom-width', 'border-color', 'border-end-end-radius', 'border-end-start-radius', 'border-image-outset', 'border-image-slice', 'border-image-width', 'border-inline-end', 'border-inline-end-color', 'border-inline-end-width', 'border-inline-start', 'border-inline-start-color', 'border-inline-start-width', 'border-left', 'border-left-color', 'border-left-width', 'border-radius', 'border-right', 'border-right-color', 'border-right-width', 'border-start-end-radius', 'border-start-start-radius', 'border-top', 'border-top-color', 'border-top-left-radius', 'border-top-right-radius', 'border-top-width', 'border-width', 'bottom', 'box-shadow', 'caret-color', 'clip', 'clip-path', 'color', 'column-count', 'column-gap', 'column-rule', 'column-rule-color', 'column-rule-width', 'column-width', 'columns', 'filter', 'flex', 'flex-basis', 'flex-grow', 'flex-shrink', 'font', 'font-size', 'font-size-adjust', 'font-stretch', 'font-variation-settings', 'font-weight', 'gap', 'grid-column-gap', 'grid-gap', 'grid-row-gap', 'grid-template-columns', 'grid-template-rows', 'height', 'inline-size', 'input-security', 'inset', 'inset-block', 'inset-block-end', 'inset-block-start', 'inset-inline', 'inset-inline-end', 'inset-inline-start', 'left', 'letter-spacing', 'line-clamp', 'line-height', 'margin', 'margin-block-end', 'margin-block-start', 'margin-bottom', 'margin-inline-end', 'margin-inline-start', 'margin-left', 'margin-right', 'margin-top', 'mask', 'mask-border', 'mask-position', 'mask-size', 'max-block-size', 'max-height', 'max-inline-size', 'max-lines', 'max-width', 'min-block-size', 'min-height', 'min-inline-size', 'min-width', 'object-position', 'offset', 'offset-anchor', 'offset-distance', 'offset-path', 'offset-position', 'offset-rotate', 'opacity', 'order', 'outline', 'outline-color', 'outline-offset', 'outline-width', 'padding', 'padding-block-end', 'padding-block-start', 'padding-bottom', 'padding-inline-end', 'padding-inline-start', 'padding-left', 'padding-right', 'padding-top', 'perspective', 'perspective-origin', 'right', 'rotate', 'row-gap', 'scale', 'scroll-margin', 'scroll-margin-block', 'scroll-margin-block-end', 'scroll-margin-block-start', 'scroll-margin-bottom', 'scroll-margin-inline', 'scroll-margin-inline-end', 'scroll-margin-inline-start', 'scroll-margin-left', 'scroll-margin-right', 'scroll-margin-top', 'scroll-padding', 'scroll-padding-block', 'scroll-padding-block-end', 'scroll-padding-block-start', 'scroll-padding-bottom', 'scroll-padding-inline', 'scroll-padding-inline-end', 'scroll-padding-inline-start', 'scroll-padding-left', 'scroll-padding-right', 'scroll-padding-top', 'scroll-snap-coordinate', 'scroll-snap-destination', 'scrollbar-color', 'shape-image-threshold', 'shape-margin', 'shape-outside', 'tab-size', 'text-decoration', 'text-decoration-color', 'text-decoration-thickness', 'text-emphasis', 'text-emphasis-color', 'text-indent', 'text-shadow', 'text-underline-offset', 'top', 'transform', 'transform-origin', 'translate', 'vertical-align', 'visibility', 'width', 'word-spacing', 'z-index', 'zoom']); 6053/** 6054 * @license 6055 * Copyright Google LLC All Rights Reserved. 6056 * 6057 * Use of this source code is governed by an MIT-style license that can be 6058 * found in the LICENSE file at https://angular.io/license 6059 */ 6060 6061function isBrowser() { 6062 return typeof window !== 'undefined' && typeof window.document !== 'undefined'; 6063} 6064 6065function isNode() {
6066 // Checking only for `process` isn't enough to identify whether or not we're in a Node 6067 // environment, because Webpack by default will polyfill the `process`. While we can discern 6068 // that Webpack polyfilled it by looking at `process.browser`, it's very Webpack-specific and 6069 // might not be future-proof. Instead we look at the stringified version of `process` which 6070 // is `[object process]` in Node and `[object Object]` when polyfilled. 6071 return typeof process !== 'undefined' && {}.toString.call(process) === '[object process]'; 6072} 6073 6074function optimizeGroupPlayer(players) { 6075 switch (players.length) { 6076 case 0: 6077 return new _angular_animations__WEBPACK_IMPORTED_MODULE_1__.NoopAnimationPlayer(); 6078 6079 case 1: 6080 return players[0]; 6081 6082 default: 6083 return new _angular_animations__WEBPACK_IMPORTED_MODULE_1__["ɵAnimationGroupPlayer"](players); 6084 } 6085} 6086 6087function normalizeKeyframes$1(driver, normalizer, element, keyframes, preStyles = new Map(), postStyles = new Map()) { 6088 const errors = []; 6089 const normalizedKeyframes = []; 6090 let previousOffset = -1; 6091 let previousKeyframe = null; 6092 keyframes.forEach(kf => { 6093 const offset = kf.get('offset');
6094 const isSameOffset = offset == previousOffset; 6095 const normalizedKeyframe = isSameOffset && previousKeyframe || new Map(); 6096 kf.forEach((val, prop) => { 6097 let normalizedProp = prop; 6098 let normalizedValue = val; 6099 6100 if (prop !== 'offset') { 6101 normalizedProp = normalizer.normalizePropertyName(normalizedProp, errors); 6102 6103 switch (normalizedValue) { 6104 case _angular_animations__WEBPACK_IMPORTED_MODULE_1__["ɵPRE_STYLE"]: 6105 normalizedValue = preStyles.get(prop); 6106 break; 6107 6108 case _angular_animations__WEBPACK_IMPORTED_MODULE_1__.AUTO_STYLE: 6109 normalizedValue = postStyles.get(prop); 6110 break; 6111 6112 default: 6113 normalizedValue = normalizer.normalizeStyleValue(prop, normalizedProp, normalizedValue, errors); 6114 break; 6115 } 6116 } 6117 6118 normalizedKeyframe.set(normalizedProp, normalizedValue); 6119 }); 6120 6121 if (!isSameOffset) { 6122 normalizedKeyframes.push(normalizedKeyframe); 6123 } 6124 6125 previousKeyframe = normalizedKeyframe; 6126 previousOffset = offset; 6127 }); 6128 6129 if (errors.length) { 6130 throw animationFailed(errors); 6131 } 6132 6133 return normalizedKeyframes; 6134} 6135 6136function listenOnPlayer(player, eventName, event, callback) { 6137 switch (eventName) { 6138 case 'start': 6139 player.onStart(() => callback(event && copyAnimationEvent(event, 'start', player))); 6140 break; 6141 6142 case 'done': 6143 player.onDone(() => callback(event && copyAnimationEvent(event, 'done', player))); 6144 break; 6145 6146 case 'destroy': 6147 player.onDestroy(() => callback(event && copyAnimationEvent(event, 'destroy', player))); 6148 break; 6149 } 6150} 6151 6152function copyAnimationEvent(e, phaseName, player) { 6153 const totalTime = player.totalTime; 6154 const disabled = player.disabled ? true : false; 6155 const event = makeAnimationEvent(e.element, e.triggerName, e.fromState, e.toState, phaseName || e.phaseName, totalTime == undefined ? e.totalTime : totalTime, disabled); 6156 const data = e['_data']; 6157 6158 if (data != null) { 6159 event['_data'] = data; 6160 } 6161 6162 return event; 6163} 6164 6165function makeAnimationEvent(element, triggerName, fromState, toState, phaseName = '', totalTime = 0, disabled) { 6166 return { 6167 element, 6168 triggerName, 6169 fromState, 6170 toState, 6171 phaseName, 6172 totalTime, 6173 disabled: !!disabled 6174 }; 6175} 6176 6177function getOrSetDefaultValue(map, key, defaultValue) { 6178 let value = map.get(key); 6179 6180 if (!value) { 6181 map.set(key, value = defaultValue); 6182 } 6183 6184 return value; 6185} 6186 6187function parseTimelineCommand(command) { 6188 const separatorPos = command.indexOf(':'); 6189 const id = command.substring(1, separatorPos); 6190 const action = command.slice(separatorPos + 1); 6191 return [id, action]; 6192} 6193 6194let _contains = (elm1, elm2) => false; 6195 6196let _query = (element, selector, multi) => { 6197 return []; 6198}; 6199 6200let _documentElement = null; 6201 6202function getParentElement(element) { 6203 const parent = element.parentNode || element.host; // consider host to support shadow DOM 6204 6205 if (parent === _documentElement) { 6206 return null; 6207 } 6208 6209 return parent; 6210} // Define utility methods for browsers and platform-server(domino) where Element 6211// and utility methods exist. 6212 6213 6214const _isNode = isNode(); 6215 6216if (_isNode || typeof Element !== 'undefined') { 6217 if (!isBrowser()) { 6218 _contains = (elm1, elm2) => elm1.contains(elm2); 6219 } else { 6220 // Read the document element in an IIFE that's been marked pure to avoid a top-level property 6221 // read that may prevent tree-shaking. 6222 _documentElement = /* @__PURE__ */(() => document.documentElement)(); 6223 6224 _contains = (elm1, elm2) => { 6225 while (elm2) { 6226 if (elm2 === elm1) { 6227 return true; 6228 } 6229 6230 elm2 = getParentElement(elm2); 6231 } 6232 6233 return false; 6234 }; 6235 } 6236 6237 _query = (element, selector, multi) => { 6238 if (multi) { 6239 return Array.from(element.querySelectorAll(selector)); 6240 } 6241 6242 const elem = element.querySelector(selector); 6243 return elem ? [elem] : []; 6244 }; 6245} 6246 6247function containsVendorPrefix(prop) { 6248 // Webkit is the only real popular vendor prefix nowadays 6249 // cc: http://shouldiprefix.com/ 6250 return prop.substring(1, 6) == 'ebkit'; // webkit or Webkit 6251} 6252 6253let _CACHED_BODY = null; 6254let _IS_WEBKIT = false;
6255 6256function validateStyleProperty(prop) { 6257 if (!_CACHED_BODY) { 6258 _CACHED_BODY = getBodyNode() || {}; 6259 _IS_WEBKIT = _CACHED_BODY.style ? 'WebkitAppearance' in _CACHED_BODY.style : false; 6260 } 6261 6262 let result = true; 6263 6264 if (_CACHED_BODY.style && !containsVendorPrefix(prop)) { 6265 result = prop in _CACHED_BODY.style; 6266 6267 if (!result && _IS_WEBKIT) { 6268 const camelProp = 'Webkit' + prop.charAt(0).toUpperCase() + prop.slice(1); 6269 result = camelProp in _CACHED_BODY.style; 6270 } 6271 } 6272 6273 return result; 6274} 6275 6276function validateWebAnimatableStyleProperty(prop) { 6277 return ANIMATABLE_PROP_SET.has(prop); 6278} 6279 6280function getBodyNode() { 6281 if (typeof document != 'undefined') { 6282 return document.body; 6283 } 6284 6285 return null; 6286} 6287 6288const containsElement = _contains; 6289const invokeQuery = _query; 6290 6291function hypenatePropsKeys(original) { 6292 const newMap = new Map(); 6293 original.forEach((val, prop) => { 6294 const newProp = prop.replace(/([a-z])([A-Z])/g, '$1-$2'); 6295 newMap.set(newProp, val); 6296 }); 6297 return newMap; 6298} 6299/** 6300 * @license 6301 * Copyright Google LLC All Rights Reserved. 6302 * 6303 * Use of this source code is governed by an MIT-style license that can be 6304 * found in the LICENSE file at https://angular.io/license 6305 */ 6306 6307/** 6308 * @publicApi 6309 */ 6310 6311 6312class NoopAnimationDriver { 6313 validateStyleProperty(prop) { 6314 return validateStyleProperty(prop); 6315 } 6316 6317 matchesElement(_element, _selector) { 6318 // This method is deprecated and no longer in use so we return false. 6319 return false; 6320 } 6321 6322 containsElement(elm1, elm2) { 6323 return containsElement(elm1, elm2); 6324 } 6325 6326 getParentElement(element) { 6327 return getParentElement(element); 6328 } 6329 6330 query(element, selector, multi) { 6331 return invokeQuery(element, selector, multi); 6332 } 6333 6334 computeStyle(element, prop, defaultValue) { 6335 return defaultValue || ''; 6336 } 6337 6338 animate(element, keyframes, duration, delay, easing, previousPlayers = [], scrubberAccessRequested) { 6339 return new _angular_animations__WEBPACK_IMPORTED_MODULE_1__.NoopAnimationPlayer(duration, delay); 6340 } 6341 6342} 6343 6344NoopAnimationDriver.ɵfac = function NoopAnimationDriver_Factory(t) { 6345 return new (t || NoopAnimationDriver)(); 6346}; 6347 6348NoopAnimationDriver.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 6349 token: NoopAnimationDriver, 6350 factory: NoopAnimationDriver.ɵfac 6351}); 6352 6353(function () { 6354 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NoopAnimationDriver, [{ 6355 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable 6356 }], null, null); 6357})(); 6358/** 6359 * @publicApi 6360 */ 6361 6362 6363class AnimationDriver {} 6364 6365AnimationDriver.NOOP = /* @__PURE__ */new NoopAnimationDriver(); 6366/** 6367 * @license 6368 * Copyright Google LLC All Rights Reserved. 6369 * 6370 * Use of this source code is governed by an MIT-style license that can be 6371 * found in the LICENSE file at https://angular.io/license 6372 */ 6373 6374const ONE_SECOND = 1000; 6375const SUBSTITUTION_EXPR_START = '{{'; 6376const SUBSTITUTION_EXPR_END = '}}'; 6377const ENTER_CLASSNAME = 'ng-enter'; 6378const LEAVE_CLASSNAME = 'ng-leave'; 6379const NG_TRIGGER_CLASSNAME = 'ng-trigger'; 6380const NG_TRIGGER_SELECTOR = '.ng-trigger'; 6381const NG_ANIMATING_CLASSNAME = 'ng-animating'; 6382const NG_ANIMATING_SELECTOR = '.ng-animating'; 6383 6384function resolveTimingValue(value) { 6385 if (typeof value == 'number') return value; 6386 const matches = value.match(/^(-?[\.\d]+)(m?s)/); 6387 if (!matches || matches.length < 2) return 0; 6388 return _convertTimeValueToMS(parseFloat(matches[1]), matches[2]); 6389} 6390 6391function _convertTimeValueToMS(value, unit) { 6392 switch (unit) { 6393 case 's': 6394 return value * ONE_SECOND; 6395 6396 default: 6397 // ms or something else 6398 return value; 6399 } 6400} 6401 6402function resolveTiming(timings, errors, allowNegativeValues) { 6403 return timings.hasOwnProperty('duration') ? timings : parseTimeExpression(timings, errors, allowNegativeValues); 6404} 6405 6406function parseTimeExpression(exp, errors, allowNegativeValues) { 6407 const regex = /^(-?[\.\d]+)(m?s)(?:\s+(-?[\.\d]+)(m?s))?(?:\s+([-a-z]+(?:\(.+?\))?))?$/i; 6408 let duration; 6409 let delay = 0; 6410 let easing = ''; 6411 6412 if (typeof exp === 'string') { 6413 const matches = exp.match(regex); 6414 6415 if (matches === null) { 6416 errors.push(invalidTimingValue(exp)); 6417 return { 6418 duration: 0, 6419 delay: 0, 6420 easing: '' 6421 }; 6422 } 6423 6424 duration = _convertTimeValueToMS(parseFloat(matches[1]), matches[2]); 6425 const delayMatch = matches[3]; 6426 6427 if (delayMatch != null) {
6428 delay = _convertTimeValueToMS(parseFloat(delayMatch), matches[4]); 6429 } 6430 6431 const easingVal = matches[5]; 6432 6433 if (easingVal) { 6434 easing = easingVal; 6435 } 6436 } else { 6437 duration = exp; 6438 } 6439 6440 if (!allowNegativeValues) { 6441 let containsErrors = false; 6442 let startIndex = errors.length; 6443 6444 if (duration < 0) { 6445 errors.push(negativeStepValue()); 6446 containsErrors = true; 6447 } 6448 6449 if (delay < 0) { 6450 errors.push(negativeDelayValue()); 6451 containsErrors = true; 6452 } 6453 6454 if (containsErrors) { 6455 errors.splice(startIndex, 0, invalidTimingValue(exp)); 6456 } 6457 } 6458 6459 return { 6460 duration, 6461 delay, 6462 easing 6463 }; 6464} 6465 6466function copyObj(obj, destination = {}) { 6467 Object.keys(obj).forEach(prop => { 6468 destination[prop] = obj[prop]; 6469 }); 6470 return destination; 6471} 6472 6473function convertToMap(obj) { 6474 const styleMap = new Map(); 6475 Object.keys(obj).forEach(prop => { 6476 const val = obj[prop]; 6477 styleMap.set(prop, val); 6478 }); 6479 return styleMap; 6480} 6481 6482function normalizeKeyframes(keyframes) { 6483 if (!keyframes.length) { 6484 return []; 6485 } 6486 6487 if (keyframes[0] instanceof Map) { 6488 return keyframes; 6489 } 6490 6491 return keyframes.map(kf => convertToMap(kf)); 6492} 6493 6494function normalizeStyles(styles) { 6495 const normalizedStyles = new Map(); 6496 6497 if (Array.isArray(styles)) { 6498 styles.forEach(data => copyStyles(data, normalizedStyles)); 6499 } else { 6500 copyStyles(styles, normalizedStyles); 6501 } 6502 6503 return normalizedStyles; 6504} 6505 6506function copyStyles(styles, destination = new Map(), backfill) { 6507 if (backfill) { 6508 for (let [prop, val] of backfill) { 6509 destination.set(prop, val); 6510 } 6511 } 6512 6513 for (let [prop, val] of styles) { 6514 destination.set(prop, val); 6515 } 6516 6517 return destination; 6518} 6519 6520function getStyleAttributeString(element, key, value) { 6521 // Return the key-value pair string to be added to the style attribute for the 6522 // given CSS style key. 6523 if (value) { 6524 return key + ':' + value + ';'; 6525 } else { 6526 return ''; 6527 } 6528} 6529 6530function writeStyleAttribute(element) { 6531 // Read the style property of the element and manually reflect it to the 6532 // style attribute. This is needed because Domino on platform-server doesn't 6533 // understand the full set of allowed CSS properties and doesn't reflect some 6534 // of them automatically. 6535 let styleAttrValue = ''; 6536 6537 for (let i = 0; i < element.style.length; i++) { 6538 const key = element.style.item(i); 6539 styleAttrValue += getStyleAttributeString(element, key, element.style.getPropertyValue(key)); 6540 } 6541 6542 for (const key in element.style) { 6543 // Skip internal Domino properties that don't need to be reflected. 6544 if (!element.style.hasOwnProperty(key) || key.startsWith('_')) { 6545 continue; 6546 } 6547 6548 const dashKey = camelCaseToDashCase(key); 6549 styleAttrValue += getStyleAttributeString(element, dashKey, element.style[key]); 6550 } 6551 6552 element.setAttribute('style', styleAttrValue); 6553} 6554 6555function setStyles(element, styles, formerStyles) { 6556 if (element['style']) { 6557 styles.forEach((val, prop) => { 6558 const camelProp = dashCaseToCamelCase(prop); 6559 6560 if (formerStyles && !formerStyles.has(prop)) { 6561 formerStyles.set(prop, element.style[camelProp]); 6562 } 6563 6564 element.style[camelProp] = val; 6565 }); // On the server set the 'style' attribute since it's not automatically reflected. 6566 6567 if (isNode()) { 6568 writeStyleAttribute(element); 6569 } 6570 } 6571} 6572 6573function eraseStyles(element, styles) { 6574 if (element['style']) { 6575 styles.forEach((_, prop) => { 6576 const camelProp = dashCaseToCamelCase(prop); 6577 element.style[camelProp] = ''; 6578 }); // On the server set the 'style' attribute since it's not automatically reflected. 6579 6580 if (isNode()) { 6581 writeStyleAttribute(element); 6582 } 6583 } 6584} 6585 6586function normalizeAnimationEntry(steps) { 6587 if (Array.isArray(steps)) { 6588 if (steps.length == 1) return steps[0]; 6589 return (0,_angular_animations__WEBPACK_IMPORTED_MODULE_1__.sequence)(steps); 6590 } 6591 6592 return steps; 6593} 6594 6595function validateStyleParams(value, options, errors) { 6596 const params = options.params || {}; 6597 const matches = extractStyleParams(value); 6598 6599 if (matches.length) {
6600 matches.forEach(varName => { 6601 if (!params.hasOwnProperty(varName)) { 6602 errors.push(invalidStyleParams(varName)); 6603 } 6604 }); 6605 } 6606} 6607 6608const PARAM_REGEX = new RegExp(`${SUBSTITUTION_EXPR_START}\\s*(.+?)\\s*${SUBSTITUTION_EXPR_END}`, 'g'); 6609 6610function extractStyleParams(value) { 6611 let params = []; 6612 6613 if (typeof value === 'string') { 6614 let match; 6615 6616 while (match = PARAM_REGEX.exec(value)) { 6617 params.push(match[1]); 6618 } 6619 6620 PARAM_REGEX.lastIndex = 0; 6621 } 6622 6623 return params; 6624} 6625 6626function interpolateParams(value, params, errors) { 6627 const original = value.toString(); 6628 const str = original.replace(PARAM_REGEX, (_, varName) => { 6629 let localVal = params[varName]; // this means that the value was never overridden by the data passed in by the user 6630 6631 if (localVal == null) { 6632 errors.push(invalidParamValue(varName)); 6633 localVal = ''; 6634 } 6635 6636 return localVal.toString(); 6637 }); // we do this to assert that numeric values stay as they are 6638 6639 return str == original ? value : str; 6640} 6641 6642function iteratorToArray(iterator) { 6643 const arr = []; 6644 let item = iterator.next(); 6645 6646 while (!item.done) { 6647 arr.push(item.value); 6648 item = iterator.next(); 6649 } 6650 6651 return arr; 6652} 6653 6654const DASH_CASE_REGEXP = /-+([a-z0-9])/g; 6655 6656function dashCaseToCamelCase(input) { 6657 return input.replace(DASH_CASE_REGEXP, (...m) => m[1].toUpperCase()); 6658} 6659 6660function camelCaseToDashCase(input) { 6661 return input.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); 6662} 6663 6664function allowPreviousPlayerStylesMerge(duration, delay) { 6665 return duration === 0 || delay === 0; 6666} 6667 6668function balancePreviousStylesIntoKeyframes(element, keyframes, previousStyles) { 6669 if (previousStyles.size && keyframes.length) { 6670 let startingKeyframe = keyframes[0]; 6671 let missingStyleProps = []; 6672 previousStyles.forEach((val, prop) => { 6673 if (!startingKeyframe.has(prop)) { 6674 missingStyleProps.push(prop); 6675 } 6676 6677 startingKeyframe.set(prop, val); 6678 }); 6679 6680 if (missingStyleProps.length) { 6681 for (let i = 1; i < keyframes.length; i++) { 6682 let kf = keyframes[i]; 6683 missingStyleProps.forEach(prop => kf.set(prop, computeStyle(element, prop))); 6684 } 6685 } 6686 } 6687 6688 return keyframes; 6689} 6690 6691function visitDslNode(visitor, node, context) { 6692 switch (node.type) { 6693 case 7 6694 /* AnimationMetadataType.Trigger */ 6695 : 6696 return visitor.visitTrigger(node, context); 6697 6698 case 0 6699 /* AnimationMetadataType.State */ 6700 : 6701 return visitor.visitState(node, context); 6702 6703 case 1 6704 /* AnimationMetadataType.Transition */ 6705 : 6706 return visitor.visitTransition(node, context); 6707 6708 case 2 6709 /* AnimationMetadataType.Sequence */ 6710 : 6711 return visitor.visitSequence(node, context); 6712 6713 case 3 6714 /* AnimationMetadataType.Group */ 6715 : 6716 return visitor.visitGroup(node, context); 6717 6718 case 4 6719 /* AnimationMetadataType.Animate */ 6720 : 6721 return visitor.visitAnimate(node, context); 6722 6723 case 5 6724 /* AnimationMetadataType.Keyframes */ 6725 : 6726 return visitor.visitKeyframes(node, context); 6727 6728 case 6 6729 /* AnimationMetadataType.Style */ 6730 : 6731 return visitor.visitStyle(node, context); 6732 6733 case 8 6734 /* AnimationMetadataType.Reference */ 6735 : 6736 return visitor.visitReference(node, context); 6737 6738 case 9 6739 /* AnimationMetadataType.AnimateChild */ 6740 : 6741 return visitor.visitAnimateChild(node, context); 6742 6743 case 10 6744 /* AnimationMetadataType.AnimateRef */ 6745 : 6746 return visitor.visitAnimateRef(node, context); 6747 6748 case 11 6749 /* AnimationMetadataType.Query */ 6750 : 6751 return visitor.visitQuery(node, context); 6752 6753 case 12 6754 /* AnimationMetadataType.Stagger */ 6755 : 6756 return visitor.visitStagger(node, context); 6757 6758 default: 6759 throw invalidNodeType(node.type); 6760 } 6761} 6762 6763function computeStyle(element, prop) { 6764 return window.getComputedStyle(element)[prop]; 6765} 6766/** 6767 * @license 6768 * Copyright Google LLC All Rights Reserved. 6769 * 6770 * Use of this source code is governed by an MIT-style license that can be 6771 * found in the LICENSE file at https://angular.io/license 6772 */ 6773 6774 6775const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode; 6776 6777function createListOfWarnings(warnings) { 6778 const LINE_START = '\n - '; 6779 return `${LINE_START}
6779${warnings.filter(Boolean).map(warning => warning).join(LINE_START)}`; 6780} 6781 6782function warnValidation(warnings) { 6783 NG_DEV_MODE && console.warn(`animation validation warnings:${createListOfWarnings(warnings)}`); 6784} 6785 6786function warnTriggerBuild(name, warnings) { 6787 NG_DEV_MODE && console.warn(`The animation trigger "${name}" has built with the following warnings:${createListOfWarnings(warnings)}`); 6788} 6789 6790function warnRegister(warnings) { 6791 NG_DEV_MODE && console.warn(`Animation built with the following warnings:${createListOfWarnings(warnings)}`); 6792} 6793 6794function triggerParsingWarnings(name, warnings) { 6795 NG_DEV_MODE && console.warn(`Animation parsing for the ${name} trigger presents the following warnings:${createListOfWarnings(warnings)}`); 6796} 6797 6798function pushUnrecognizedPropertiesWarning(warnings, props) { 6799 if (props.length) { 6800 warnings.push(`The following provided properties are not recognized: ${props.join(', ')}`); 6801 } 6802} 6803/** 6804 * @license 6805 * Copyright Google LLC All Rights Reserved. 6806 * 6807 * Use of this source code is governed by an MIT-style license that can be 6808 * found in the LICENSE file at https://angular.io/license 6809 */ 6810 6811 6812const ANY_STATE = '*'; 6813 6814function parseTransitionExpr(transitionValue, errors) { 6815 const expressions = []; 6816 6817 if (typeof transitionValue == 'string') { 6818 transitionValue.split(/\s*,\s*/).forEach(str => parseInnerTransitionStr(str, expressions, errors)); 6819 } else { 6820 expressions.push(transitionValue); 6821 } 6822 6823 return expressions; 6824} 6825 6826function parseInnerTransitionStr(eventStr, expressions, errors) { 6827 if (eventStr[0] == ':') { 6828 const result = parseAnimationAlias(eventStr, errors); 6829 6830 if (typeof result == 'function') { 6831 expressions.push(result); 6832 return; 6833 } 6834 6835 eventStr = result; 6836 } 6837 6838 const match = eventStr.match(/^(\*|[-\w]+)\s*(<?[=-]>)\s*(\*|[-\w]+)$/); 6839 6840 if (match == null || match.length < 4) { 6841 errors.push(invalidExpression(eventStr)); 6842 return expressions; 6843 } 6844 6845 const fromState = match[1]; 6846 const separator = match[2]; 6847 const toState = match[3]; 6848 expressions.push(makeLambdaFromStates(fromState, toState)); 6849 const isFullAnyStateExpr = fromState == ANY_STATE && toState == ANY_STATE; 6850 6851 if (separator[0] == '<' && !isFullAnyStateExpr) { 6852 expressions.push(makeLambdaFromStates(toState, fromState)); 6853 } 6854} 6855 6856function parseAnimationAlias(alias, errors) { 6857 switch (alias) { 6858 case ':enter': 6859 return 'void => *'; 6860 6861 case ':leave': 6862 return '* => void'; 6863 6864 case ':increment': 6865 return (fromState, toState) => parseFloat(toState) > parseFloat(fromState); 6866 6867 case ':decrement': 6868 return (fromState, toState) => parseFloat(toState) < parseFloat(fromState); 6869 6870 default: 6871 errors.push(invalidTransitionAlias(alias)); 6872 return '* => *'; 6873 } 6874} // DO NOT REFACTOR ... keep the follow set instantiations 6875// with the values intact (closure compiler for some reason 6876// removes follow-up lines that add the values outside of 6877// the constructor... 6878 6879 6880const TRUE_BOOLEAN_VALUES = new Set(['true', '1']); 6881const FALSE_BOOLEAN_VALUES = new Set(['false', '0']); 6882 6883function makeLambdaFromStates(lhs, rhs) { 6884 const LHS_MATCH_BOOLEAN = TRUE_BOOLEAN_VALUES.has(lhs) || FALSE_BOOLEAN_VALUES.has(lhs); 6885 const RHS_MATCH_BOOLEAN = TRUE_BOOLEAN_VALUES.has(rhs) || FALSE_BOOLEAN_VALUES.has(rhs); 6886 return (fromState, toState) => { 6887 let lhsMatch = lhs == ANY_STATE || lhs == fromState; 6888 let rhsMatch = rhs == ANY_STATE || rhs == toState; 6889 6890 if (!lhsMatch && LHS_MATCH_BOOLEAN && typeof fromState === 'boolean') { 6891 lhsMatch = fromState ? TRUE_BOOLEAN_VALUES.has(lhs) : FALSE_BOOLEAN_VALUES.has(lhs); 6892 } 6893 6894 if (!rhsMatch && RHS_MATCH_BOOLEAN && typeof toState === 'boolean') { 6895 rhsMatch = toState ? TRUE_BOOLEAN_VALUES.has(rhs) : FALSE_BOOLEAN_VALUES.has(rhs); 6896 } 6897 6898 return lhsMatch && rhsMatch; 6899 }; 6900} 6901/** 6902 * @license 6903 * Copyright Google LLC All Rights Reserved. 6904 * 6905 * Use of this source code is governed by an MIT-style license that can be 6906 * found in the LICENSE file at https://angular.io/license 6907 */ 6908 6909 6910const SELF_TOKEN = ':self'; 6911const SELF_TOKEN_REGEX = new RegExp(`\s*${SELF_TOKEN}\s*,?`, 'g'); 6912/* 6913 * [Validation] 6914 * The visitor code below will traverse the animation AST generated by the animation verb functions 6915 * (the output is a tree of objects) and attempt to perform a series of validations on the data. The 6916 * following corner-cases will be validated: 6917 * 6918 * 1. Overlap of animations 6919 * Given that a CSS property cannot be animated in more than one place at the same time, it's 6920 * important that this behavior is detected and validated. The way in which this occurs is that 6921 * each time a style property is examined, a string-map containing the property will be updated with 6922 * the start and end times for when the property is used within an animation step. 6923 * 6924 * If there are two or more parallel animations that are currently running (these are invoked by the 6925 * group()) on the same element then the validator will throw an error. Since the start/end timing 6926 * values are collected for each property then if the current animation step is animating the same 6927 * property and its timing values fall anywhere into the window of time that the property is 6928 * currently being animated within then this is what causes an error. 6929 * 6930 * 2. Timing values 6931 * The validator will validate to see if a timing value of `duration delay easing` or 6932 * `durationNumber` is valid or not. 6933 * 6934 * (note that upon validation the code below will replace the timing data with an object c
6934ontaining 6935 * {duration,delay,easing}. 6936 * 6937 * 3. Offset Validation 6938 * Each of the style() calls are allowed to have an offset value when placed inside of keyframes(). 6939 * Offsets within keyframes() are considered valid when: 6940 * 6941 * - No offsets are used at all 6942 * - Each style() entry contains an offset value 6943 * - Each offset is between 0 and 1 6944 * - Each offset is greater to or equal than the previous one 6945 * 6946 * Otherwise an error will be thrown. 6947 */ 6948 6949function buildAnimationAst(driver, metadata, errors, warnings) { 6950 return new AnimationAstBuilderVisitor(driver).build(metadata, errors, warnings); 6951} 6952 6953const ROOT_SELECTOR = ''; 6954 6955class AnimationAstBuilderVisitor { 6956 constructor(_driver) { 6957 this._driver = _driver; 6958 } 6959 6960 build(metadata, errors, warnings) { 6961 const context = new AnimationAstBuilderContext(errors); 6962 6963 this._resetContextStyleTimingState(context); 6964 6965 const ast = visitDslNode(this, normalizeAnimationEntry(metadata), context); 6966 6967 if (typeof ngDevMode === 'undefined' || ngDevMode) { 6968 if (context.unsupportedCSSPropertiesFound.size) { 6969 pushUnrecognizedPropertiesWarning(warnings, [...context.unsupportedCSSPropertiesFound.keys()]); 6970 } 6971 } 6972 6973 return ast; 6974 } 6975 6976 _resetContextStyleTimingState(context) { 6977 context.currentQuerySelector = ROOT_SELECTOR; 6978 context.collectedStyles = new Map(); 6979 context.collectedStyles.set(ROOT_SELECTOR, new Map()); 6980 context.currentTime = 0; 6981 } 6982 6983 visitTrigger(metadata, context) { 6984 let queryCount = context.queryCount = 0; 6985 let depCount = context.depCount = 0; 6986 const states = []; 6987 const transitions = []; 6988 6989 if (metadata.name.charAt(0) == '@') { 6990 context.errors.push(invalidTrigger()); 6991 } 6992 6993 metadata.definitions.forEach(def => { 6994 this._resetContextStyleTimingState(context); 6995 6996 if (def.type == 0 6997 /* AnimationMetadataType.State */ 6998 ) { 6999 const stateDef = def; 7000 const name = stateDef.name; 7001 name.toString().split(/\s*,\s*/).forEach(n => { 7002 stateDef.name = n; 7003 states.push(this.visitState(stateDef, context)); 7004 }); 7005 stateDef.name = name; 7006 } else if (def.type == 1 7007 /* AnimationMetadataType.Transition */ 7008 ) { 7009 const transition = this.visitTransition(def, context); 7010 queryCount += transition.queryCount; 7011 depCount += transition.depCount; 7012 transitions.push(transition); 7013 } else { 7014 context.errors.push(invalidDefinition()); 7015 } 7016 }); 7017 return { 7018 type: 7 7019 /* AnimationMetadataType.Trigger */ 7020 , 7021 name: metadata.name, 7022 states, 7023 transitions, 7024 queryCount, 7025 depCount, 7026 options: null 7027 }; 7028 } 7029 7030 visitState(metadata, context) { 7031 const styleAst = this.visitStyle(metadata.styles, context); 7032 const astParams = metadata.options && metadata.options.params || null; 7033 7034 if (styleAst.containsDynamicStyles) { 7035 const missingSubs = new Set(); 7036 const params = astParams || {}; 7037 styleAst.styles.forEach(style => { 7038 if (style instanceof Map) { 7039 style.forEach(value => { 7040 extractStyleParams(value).forEach(sub => { 7041 if (!params.hasOwnProperty(sub)) { 7042 missingSubs.add(sub); 7043 } 7044 }); 7045 }); 7046 } 7047 }); 7048 7049 if (missingSubs.size) { 7050 const missingSubsArr = iteratorToArray(missingSubs.values()); 7051 context.errors.push(invalidState(metadata.name, missingSubsArr)); 7052 } 7053 } 7054 7055 return { 7056 type: 0 7057 /* AnimationMetadataType.State */ 7058 , 7059 name: metadata.name, 7060 style: styleAst, 7061 options: astParams ? { 7062 params: astParams 7063 } : null 7064 }; 7065 } 7066 7067 visitTransition(metadata, context) { 7068 context.queryCount = 0; 7069 context.depCount = 0; 7070 const animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context); 7071 const matchers = parseTransitionExpr(metadata.expr, context.errors); 7072 return { 7073 type: 1 7074 /* AnimationMetadataType.Transition */ 7075 , 7076 matchers, 7077 animation, 7078 queryCount: context.queryCount, 7079 depCount: context.depCount, 7080 options: normalizeAnimationOptions(metadata.options) 7081 }; 7082 } 7083 7084 visitSequence(metadata, context) { 7085 return { 7086 type: 2 7087 /* AnimationMetadataType.Sequence */ 7088 , 7089 steps: metadata.steps.map(s => visitDslNode(this, s, context)), 7090 options: normalizeAnimationOptions(metadata.options) 7091 }; 7092 } 7093 7094 visitGroup(metadata, context) { 7095 const currentTime = context.currentTime; 7096 let furthestTime = 0; 7097 const steps = metadata.steps.map(step => { 7098 context.currentTime = currentTime; 7099 const innerAst = visitDslNode(this, step, context); 7100 furthestTime = Math.max(furthestTime, context.currentTime); 7101 return innerAst; 7102 }); 7103 context.currentTime = furthestTime; 7104 return { 7105 type: 3
vendor: 9,292 bytes, lines 7106-7415
7106 /* AnimationMetadataType.Group */ 7107 , 7108 steps, 7109 options: normalizeAnimationOptions(metadata.options) 7110 }; 7111 } 7112 7113 visitAnimate(metadata, context) { 7114 const timingAst = constructTimingAst(metadata.timings, context.errors); 7115 context.currentAnimateTimings = timingAst; 7116 let styleAst; 7117 let styleMetadata = metadata.styles ? metadata.styles : (0,_angular_animations__WEBPACK_IMPORTED_MODULE_1__.style)({}); 7118 7119 if (styleMetadata.type == 5 7120 /* AnimationMetadataType.Keyframes */ 7121 ) { 7122 styleAst = this.visitKeyframes(styleMetadata, context); 7123 } else { 7124 let styleMetadata = metadata.styles; 7125 let isEmpty = false; 7126 7127 if (!styleMetadata) { 7128 isEmpty = true; 7129 const newStyleData = {}; 7130 7131 if (timingAst.easing) { 7132 newStyleData['easing'] = timingAst.easing; 7133 } 7134 7135 styleMetadata = (0,_angular_animations__WEBPACK_IMPORTED_MODULE_1__.style)(newStyleData); 7136 } 7137 7138 context.currentTime += timingAst.duration + timingAst.delay; 7139 7140 const _styleAst = this.visitStyle(styleMetadata, context); 7141 7142 _styleAst.isEmptyStep = isEmpty; 7143 styleAst = _styleAst; 7144 } 7145 7146 context.currentAnimateTimings = null; 7147 return { 7148 type: 4 7149 /* AnimationMetadataType.Animate */ 7150 , 7151 timings: timingAst, 7152 style: styleAst, 7153 options: null 7154 }; 7155 } 7156 7157 visitStyle(metadata, context) { 7158 const ast = this._makeStyleAst(metadata, context); 7159 7160 this._validateStyleAst(ast, context); 7161 7162 return ast; 7163 } 7164 7165 _makeStyleAst(metadata, context) { 7166 const styles = []; 7167 const metadataStyles = Array.isArray(metadata.styles) ? metadata.styles : [metadata.styles]; 7168 7169 for (let styleTuple of metadataStyles) { 7170 if (typeof styleTuple === 'string') { 7171 if (styleTuple === _angular_animations__WEBPACK_IMPORTED_MODULE_1__.AUTO_STYLE) { 7172 styles.push(styleTuple); 7173 } else { 7174 context.errors.push(invalidStyleValue(styleTuple)); 7175 } 7176 } else { 7177 styles.push(convertToMap(styleTuple)); 7178 } 7179 } 7180 7181 let containsDynamicStyles = false; 7182 let collectedEasing = null; 7183 styles.forEach(styleData => { 7184 if (styleData instanceof Map) { 7185 if (styleData.has('easing')) { 7186 collectedEasing = styleData.get('easing'); 7187 styleData.delete('easing'); 7188 } 7189 7190 if (!containsDynamicStyles) { 7191 for (let value of styleData.values()) { 7192 if (value.toString().indexOf(SUBSTITUTION_EXPR_START) >= 0) { 7193 containsDynamicStyles = true; 7194 break; 7195 } 7196 } 7197 } 7198 } 7199 }); 7200 return { 7201 type: 6 7202 /* AnimationMetadataType.Style */ 7203 , 7204 styles, 7205 easing: collectedEasing, 7206 offset: metadata.offset, 7207 containsDynamicStyles, 7208 options: null 7209 }; 7210 } 7211 7212 _validateStyleAst(ast, context) { 7213 const timings = context.currentAnimateTimings; 7214 let endTime = context.currentTime; 7215 let startTime = context.currentTime; 7216 7217 if (timings && startTime > 0) { 7218 startTime -= timings.duration + timings.delay; 7219 } 7220 7221 ast.styles.forEach(tuple => { 7222 if (typeof tuple === 'string') return; 7223 tuple.forEach((value, prop) => { 7224 if (typeof ngDevMode === 'undefined' || ngDevMode) { 7225 if (!this._driver.validateStyleProperty(prop)) { 7226 tuple.delete(prop); 7227 context.unsupportedCSSPropertiesFound.add(prop); 7228 return; 7229 } 7230 } // This is guaranteed to have a defined Map at this querySelector location making it 7231 // safe to add the assertion here. It is set as a default empty map in prior methods. 7232 7233 7234 const collectedStyles = context.collectedStyles.get(context.currentQuerySelector); 7235 const collectedEntry = collectedStyles.get(prop); 7236 let updateCollectedStyle = true; 7237 7238 if (collectedEntry) { 7239 if (startTime != endTime && startTime >= collectedEntry.startTime && endTime <= collectedEntry.endTime) { 7240 context.errors.push(invalidParallelAnimation(prop, collectedEntry.startTime, collectedEntry.endTime, startTime, endTime)); 7241 updateCollectedStyle = false; 7242 } // we always choose the smaller start time value since we 7243 // want to have a record of the entire animation window where 7244 // the style property is being animated in between 7245 7246 7247 startTime = collectedEntry.startTime; 7248 } 7249 7250 if (updateCollectedStyle) { 7251 collectedStyles.set(prop, { 7252 startTime, 7253 endTime 7254 }); 7255 } 7256 7257 if (context.options) { 7258 validateStyleParams(value, context.options, context.errors); 7259 } 7260 }); 7261 }); 7262 } 7263 7264 visitKeyframes(metadata, context) { 7265 const ast = { 7266 type: 5 7267 /* AnimationMetadataType.Keyframes */ 7268 , 7269 styles: [], 7270 options: null 7271 }; 7272 7273 if (!context.currentAnimateTimings) { 7274 context.errors.push(invalidKeyframes()); 7275 return ast; 7276 } 7277 7278 const MAX_KEYFRAME_OFFSET = 1; 7279 let totalKeyframesWithOffsets = 0; 7280 const offsets = []; 7281 let offsetsOutOfOrder = false; 7282 let keyframesOutOfRange = false; 7283 let previousOffset = 0; 7284 const keyframes = metadata.steps.map(styles => { 7285 const style = this._makeStyleAst(styles, context); 7286 7287 let offsetVal = style.offset != null ? style.offset : consumeOffset(style.styles); 7288 let offset = 0; 7289 7290 if (offsetVal != null) { 7291 totalKeyframesWithOffsets++; 7292 offset = style.offset = offsetVal; 7293 } 7294 7295 keyframesOutOfRange = keyframesOutOfRange || offset < 0 || offset > 1; 7296 offsetsOutOfOrder = offsetsOutOfOrder || offset < previousOffset; 7297 previousOffset = offset; 7298 offsets.push(offset); 7299 return style; 7300 }); 7301 7302 if (keyframesOutOfRange) { 7303 context.errors.push(invalidOffset()); 7304 } 7305 7306 if (offsetsOutOfOrder) { 7307 context.errors.push(keyframeOffsetsOutOfOrder()); 7308 } 7309 7310 const length = metadata.steps.length; 7311 let generatedOffset = 0; 7312 7313 if (totalKeyframesWithOffsets > 0 && totalKeyframesWithOffsets < length) { 7314 context.errors.push(keyframesMissingOffsets()); 7315 } else if (totalKeyframesWithOffsets == 0) { 7316 generatedOffset = MAX_KEYFRAME_OFFSET / (length - 1); 7317 } 7318 7319 const limit = length - 1; 7320 const currentTime = context.currentTime; 7321 const currentAnimateTimings = context.currentAnimateTimings; 7322 const animateDuration = currentAnimateTimings.duration; 7323 keyframes.forEach((kf, i) => { 7324 const offset = generatedOffset > 0 ? i == limit ? 1 : generatedOffset * i : offsets[i]; 7325 const durationUpToThisFrame = offset * animateDuration; 7326 context.currentTime = currentTime + currentAnimateTimings.delay + durationUpToThisFrame; 7327 currentAnimateTimings.duration = durationUpToThisFrame; 7328 7329 this._validateStyleAst(kf, context); 7330 7331 kf.offset = offset; 7332 ast.styles.push(kf); 7333 }); 7334 return ast; 7335 } 7336 7337 visitReference(metadata, context) { 7338 return { 7339 type: 8 7340 /* AnimationMetadataType.Reference */ 7341 , 7342 animation: visitDslNode(this, normalizeAnimationEntry(metadata.animation), context), 7343 options: normalizeAnimationOptions(metadata.options) 7344 }; 7345 } 7346 7347 visitAnimateChild(metadata, context) { 7348 context.depCount++; 7349 return { 7350 type: 9 7351 /* AnimationMetadataType.AnimateChild */ 7352 , 7353 options: normalizeAnimationOptions(metadata.options) 7354 }; 7355 } 7356 7357 visitAnimateRef(metadata, context) { 7358 return { 7359 type: 10 7360 /* AnimationMetadataType.AnimateRef */ 7361 , 7362 animation: this.visitReference(metadata.animation, context), 7363 options: normalizeAnimationOptions(metadata.options) 7364 }; 7365 } 7366 7367 visitQuery(metadata, context) { 7368 const parentSelector = context.currentQuerySelector; 7369 const options = metadata.options || {}; 7370 context.queryCount++; 7371 context.currentQuery = metadata; 7372 const [selector, includeSelf] = normalizeSelector(metadata.selector); 7373 context.currentQuerySelector = parentSelector.length ? parentSelector + ' ' + selector : selector; 7374 getOrSetDefaultValue(context.collectedStyles, context.currentQuerySelector, new Map()); 7375 const animation = visitDslNode(this, normalizeAnimationEntry(metadata.animation), context); 7376 context.currentQuery = null; 7377 context.currentQuerySelector = parentSelector; 7378 return { 7379 type: 11 7380 /* AnimationMetadataType.Query */ 7381 , 7382 selector, 7383 limit: options.limit || 0, 7384 optional: !!options.optional, 7385 includeSelf, 7386 animation, 7387 originalSelector: metadata.selector, 7388 options: normalizeAnimationOptions(metadata.options) 7389 }; 7390 } 7391 7392 visitStagger(metadata, context) { 7393 if (!context.currentQuery) { 7394 context.errors.push(invalidStagger()); 7395 } 7396 7397 const timings = metadata.timings === 'full' ? { 7398 duration: 0, 7399 delay: 0, 7400 easing: 'full' 7401 } : resolveTiming(metadata.timings, context.errors, true); 7402 return { 7403 type: 12 7404 /* AnimationMetadataType.Stagger */ 7405 , 7406 animation: visitDslNode(this, normalizeAnimationEntry(metadata.animation), context), 7407 timings, 7408 options: null 7409 }; 7410 } 7411 7412} 7413 7414function normalizeSelector(selector) { 7415 const hasAmpersand = selector.split(/\s*,\s*/).find(token => token == SELF_TOKEN) ? true : false;
7416 7417 if (hasAmpersand) { 7418 selector = selector.replace(SELF_TOKEN_REGEX, ''); 7419 } // Note: the :enter and :leave aren't normalized here since those 7420 // selectors are filled in at runtime during timeline building 7421 7422 7423 selector = selector.replace(/@\*/g, NG_TRIGGER_SELECTOR).replace(/@\w+/g, match => NG_TRIGGER_SELECTOR + '-' + match.slice(1)).replace(/:animating/g, NG_ANIMATING_SELECTOR); 7424 return [selector, hasAmpersand]; 7425} 7426 7427function normalizeParams(obj) { 7428 return obj ? copyObj(obj) : null; 7429} 7430 7431class AnimationAstBuilderContext { 7432 constructor(errors) { 7433 this.errors = errors; 7434 this.queryCount = 0; 7435 this.depCount = 0; 7436 this.currentTransition = null; 7437 this.currentQuery = null; 7438 this.currentQuerySelector = null; 7439 this.currentAnimateTimings = null; 7440 this.currentTime = 0; 7441 this.collectedStyles = new Map(); 7442 this.options = null; 7443 this.unsupportedCSSPropertiesFound = new Set(); 7444 } 7445 7446} 7447 7448function consumeOffset(styles) { 7449 if (typeof styles == 'string') return null; 7450 let offset = null; 7451 7452 if (Array.isArray(styles)) { 7453 styles.forEach(styleTuple => { 7454 if (styleTuple instanceof Map && styleTuple.has('offset')) { 7455 const obj = styleTuple; 7456 offset = parseFloat(obj.get('offset')); 7457 obj.delete('offset'); 7458 } 7459 }); 7460 } else if (styles instanceof Map && styles.has('offset')) { 7461 const obj = styles; 7462 offset = parseFloat(obj.get('offset')); 7463 obj.delete('offset'); 7464 } 7465 7466 return offset; 7467} 7468 7469function constructTimingAst(value, errors) { 7470 if (value.hasOwnProperty('duration')) { 7471 return value; 7472 } 7473 7474 if (typeof value == 'number') { 7475 const duration = resolveTiming(value, errors).duration; 7476 return makeTimingAst(duration, 0, ''); 7477 } 7478 7479 const strValue = value; 7480 const isDynamic = strValue.split(/\s+/).some(v => v.charAt(0) == '{' && v.charAt(1) == '{'); 7481 7482 if (isDynamic) { 7483 const ast = makeTimingAst(0, 0, ''); 7484 ast.dynamic = true; 7485 ast.strValue = strValue; 7486 return ast; 7487 } 7488 7489 const timings = resolveTiming(strValue, errors); 7490 return makeTimingAst(timings.duration, timings.delay, timings.easing); 7491} 7492 7493function normalizeAnimationOptions(options) { 7494 if (options) { 7495 options = copyObj(options); 7496 7497 if (options['params']) { 7498 options['params'] = normalizeParams(options['params']); 7499 } 7500 } else { 7501 options = {}; 7502 } 7503 7504 return options; 7505} 7506 7507function makeTimingAst(duration, delay, easing) { 7508 return { 7509 duration, 7510 delay, 7511 easing 7512 }; 7513} 7514
7515function createTimelineInstruction(element, keyframes, preStyleProps, postStyleProps, duration, delay, easing = null, subTimeline = false) { 7516 return { 7517 type: 1 7518 /* AnimationTransitionInstructionType.TimelineAnimation */ 7519 , 7520 element, 7521 keyframes, 7522 preStyleProps, 7523 postStyleProps, 7524 duration, 7525 delay, 7526 totalTime: duration + delay, 7527 easing, 7528 subTimeline 7529 }; 7530} 7531 7532class ElementInstructionMap { 7533 constructor() { 7534 this._map = new Map(); 7535 } 7536 7537 get(element) { 7538 return this._map.get(element) || []; 7539 } 7540 7541 append(element, instructions) { 7542 let existingInstructions = this._map.get(element); 7543 7544 if (!existingInstructions) { 7545 this._map.set(element, existingInstructions = []); 7546 } 7547 7548 existingInstructions.push(...instructions); 7549 } 7550 7551 has(element) { 7552 return this._map.has(element); 7553 } 7554 7555 clear() { 7556 this._map.clear(); 7557 } 7558 7559} 7560/** 7561 * @license 7562 * Copyright Google LLC All Rights Reserved. 7563 * 7564 * Use of this source code is governed by an MIT-style license that can be 7565 * found in the LICENSE file at https://angular.io/license 7566 */ 7567 7568 7569const ONE_FRAME_IN_MILLISECONDS = 1; 7570const ENTER_TOKEN = ':enter'; 7571const ENTER_TOKEN_REGEX = new RegExp(ENTER_TOKEN, 'g'); 7572const LEAVE_TOKEN = ':leave'; 7573const LEAVE_TOKEN_REGEX = new RegExp(LEAVE_TOKEN, 'g'); 7574/* 7575 * The code within this file aims to generate web-animations-compatible keyframes from Angular's 7576 * animation DSL code. 7577 * 7578 * The code below will be converted from: 7579 * 7580 * ``` 7581 * sequence([ 7582 * style({ opacity: 0 }), 7583 * animate(1000, style({ opacity: 0 })) 7584 * ]) 7585 * ``` 7586 * 7587 * To: 7588 * ``` 7589 * keyframes = [{ opacity: 0, offset: 0 }, { opacity: 1, offset: 1 }] 7590 * duration = 1000 7591 * delay = 0 7592 * easing = '' 7593 * ``` 7594 * 7595 * For this operation to cover the combination of animation verbs (style, animate, group, etc...) a 7596 * combination of AST traversal and merge-sort-like algorithms are used. 7597 * 7598 * [AST Traversal] 7599 * Each of the animation verbs, when executed, will return an string-map object representing what 7600 * type of action it is (style, animate, group, etc...) and the data associated with it. This means 7601 * that when functional composition mix of these functions is evaluated (like in the example above) 7602 * then it will end up producing a tree of objects representing the animation itself. 7603 * 7604 * When this animation object tree is processed by the visitor code below it will visit each of the 7605 * verb statements within the visitor. And during each visit it will build the context of the 7606 * animation keyframes by interacting with the `TimelineBuilder`. 7607 * 7608 * [TimelineBuilder] 7609 * This class is responsible for tracking the styles and building a series of keyframe objects for a 7610 * timeline between a start and end time. The builder starts off with an initial timeline and each 7611 * time the AST comes across a `group()`, `keyframes()` or a combination of the two within a 7612 * `sequence()` then it will generate a sub timeline for each step as well as a new one after 7613 * they are complete. 7614 * 7615 * As the AST is traversed, the timing state on each of the timelines will be incremented. If a sub 7616 * timeline was created (based on one of the cases above) then the parent timeline will attempt to 7617 * merge the styles used within the sub timelines into itself (only with group() this will happen). 7618 * This happens with a merge operation (much like how the merge works in mergeSort) and it will only 7619 * copy the most recently used styles from the sub timelines into the parent timeline. This ensures 7620 * that if the styles are used later on in another phase of the animation then they will be the most 7621 * up-to-date values. 7622 * 7623 * [How Missing Styles Are Updated] 7624 * Each timeline has a `backFill` property which is responsible for filling in new styles into 7625 * already processed keyframes if a new style shows up later within the animation sequence. 7626 * 7627 * ``` 7628 * sequence([ 7629 * style({ width: 0 }), 7630 * animate(1000, style({ width: 100 })), 7631 * animate(1000, style({ width: 200 })), 7632 * animate(1000, style({ width: 300 })) 7633 * animate(1000, style({ width: 400, height: 400 })) // notice how `height` doesn't exist anywhere 7634 * else 7635 * ]) 7636 * ``` 7637 * 7638 * What is happening here is that the `height` value is added later in the sequence, but is missing 7639 * from all previous animation steps. Therefore when a keyframe is created it would also be missing 7640 * from all previous keyframes up until where it is first used. For the timeline keyframe generation 7641 * to properly fill in the style it will place the previous value (the value from the parent 7642 * timeline) or a default value of `*` into the backFill map. The `copyStyles` method in util.ts 7643 * handles propagating that backfill map to the styles object. 7644 * 7645 * When a sub-timeline is created it will have its own backFill property. This is done so that 7646 * styles present within the sub-timeline do not accidentally seep into the previous/future timeline 7647 * keyframes 7648 * 7649 * [Validation] 7650 * The code in this file is not responsible for validation. That functionality happens with within 7651 * the `AnimationValidatorVisitor` code. 7652 */ 7653 7654function buildAnimationTimelines(driver, rootElement, ast, enterClassName, leaveClassName, startingStyles = new Map(), finalStyles = new Map(), options, subInstru
vendor: 22,926 bytes, lines 7654-8340
7654ctions, errors = []) { 7655 return new AnimationTimelineBuilderVisitor().buildKeyframes(driver, rootElement, ast, enterClassName, leaveClassName, startingStyles, finalStyles, options, subInstructions, errors); 7656} 7657 7658class AnimationTimelineBuilderVisitor { 7659 buildKeyframes(driver, rootElement, ast, enterClassName, leaveClassName, startingStyles, finalStyles, options, subInstructions, errors = []) { 7660 subInstructions = subInstructions || new ElementInstructionMap(); 7661 const context = new AnimationTimelineContext(driver, rootElement, subInstructions, enterClassName, leaveClassName, errors, []); 7662 context.options = options; 7663 const delay = options.delay ? resolveTimingValue(options.delay) : 0; 7664 context.currentTimeline.delayNextStep(delay); 7665 context.currentTimeline.setStyles([startingStyles], null, context.errors, options); 7666 visitDslNode(this, ast, context); // this checks to see if an actual animation happened 7667 7668 const timelines = context.timelines.filter(timeline => timeline.containsAnimation()); // note: we just want to apply the final styles for the rootElement, so we do not 7669 // just apply the styles to the last timeline but the last timeline which 7670 // element is the root one (basically `*`-styles are replaced with the actual 7671 // state style values only for the root element) 7672 7673 if (timelines.length && finalStyles.size) { 7674 let lastRootTimeline; 7675 7676 for (let i = timelines.length - 1; i >= 0; i--) { 7677 const timeline = timelines[i]; 7678 7679 if (timeline.element === rootElement) { 7680 lastRootTimeline = timeline; 7681 break; 7682 } 7683 } 7684 7685 if (lastRootTimeline && !lastRootTimeline.allowOnlyTimelineStyles()) { 7686 lastRootTimeline.setStyles([finalStyles], null, context.errors, options); 7687 } 7688 } 7689 7690 return timelines.length ? timelines.map(timeline => timeline.buildKeyframes()) : [createTimelineInstruction(rootElement, [], [], [], 0, delay, '', false)]; 7691 } 7692 7693 visitTrigger(ast, context) {// these values are not visited in this AST 7694 } 7695 7696 visitState(ast, context) {// these values are not visited in this AST 7697 } 7698 7699 visitTransition(ast, context) {// these values are not visited in this AST 7700 } 7701 7702 visitAnimateChild(ast, context) { 7703 const elementInstructions = context.subInstructions.get(context.element); 7704 7705 if (elementInstructions) { 7706 const innerContext = context.createSubContext(ast.options); 7707 const startTime = context.currentTimeline.currentTime; 7708 7709 const endTime = this._visitSubInstructions(elementInstructions, innerContext, innerContext.options); 7710 7711 if (startTime != endTime) { 7712 // we do this on the upper context because we created a sub context for 7713 // the sub child animations 7714 context.transformIntoNewTimeline(endTime); 7715 } 7716 } 7717 7718 context.previousNode = ast; 7719 } 7720 7721 visitAnimateRef(ast, context) { 7722 const innerContext = context.createSubContext(ast.options); 7723 innerContext.transformIntoNewTimeline(); 7724 7725 this._applyAnimationRefDelays([ast.options, ast.animation.options], context, innerContext); 7726 7727 this.visitReference(ast.animation, innerContext); 7728 context.transformIntoNewTimeline(innerContext.currentTimeline.currentTime); 7729 context.previousNode = ast; 7730 } 7731 7732 _applyAnimationRefDelays(animationsRefsOptions, context, innerContext) { 7733 for (const animationRefOptions of animationsRefsOptions) { 7734 const animationDelay = animationRefOptions?.delay; 7735 7736 if (animationDelay) { 7737 const animationDelayValue = typeof animationDelay === 'number' ? animationDelay : resolveTimingValue(interpolateParams(animationDelay, animationRefOptions?.params ?? {}, context.errors)); 7738 innerContext.delayNextStep(animationDelayValue); 7739 } 7740 } 7741 } 7742 7743 _visitSubInstructions(instructions, context, options) { 7744 const startTime = context.currentTimeline.currentTime; 7745 let furthestTime = startTime; // this is a special-case for when a user wants to skip a sub 7746 // animation from being fired entirely. 7747 7748 const duration = options.duration != null ? resolveTimingValue(options.duration) : null; 7749 const delay = options.delay != null ? resolveTimingValue(options.delay) : null; 7750 7751 if (duration !== 0) { 7752 instructions.forEach(instruction => { 7753 const instructionTimings = context.appendInstructionToTimeline(instruction, duration, delay); 7754 furthestTime = Math.max(furthestTime, instructionTimings.duration + instructionTimings.delay); 7755 }); 7756 } 7757 7758 return furthestTime; 7759 } 7760 7761 visitReference(ast, context) { 7762 context.updateOptions(ast.options, true); 7763 visitDslNode(this, ast.animation, context); 7764 context.previousNode = ast; 7765 } 7766 7767 visitSequence(ast, context) { 7768 const subContextCount = context.subContextCount; 7769 let ctx = context; 7770 const options = ast.options; 7771 7772 if (options && (options.params || options.delay)) { 7773 ctx = context.createSubContext(options); 7774 ctx.transformIntoNewTimeline(); 7775 7776 if (options.delay != null) { 7777 if (ctx.previousNode.type == 6 7778 /* AnimationMetadataType.Style */ 7779 ) { 7780 ctx.currentTimeline.snapshotCurrentStyles(); 7781 ctx.previousNode = DEFAULT_NOOP_PREVIOUS_NODE; 7782 } 7783 7784 const delay = resolveTimingValue(options.delay); 7785 ctx.delayNextStep(delay); 7786 } 7787 } 7788 7789 if (ast.steps.length) { 7790 ast.steps.forEach(s => visitDslNode(this, s, ctx)); // this is here just in case the inner steps only contain or end with a style() call 7791 7792 ctx.currentTimeline.applyStylesToKeyframe(); // this means that some animation function within the sequence 7793 // ended up creating a sub timeline (which means the current 7794 // timeline cannot overlap with the contents of the sequence) 7795 7796 if (ctx.subContextCount > subContextCount) { 7797 ctx.transformIntoNewTimeline(); 7798 } 7799 } 7800 7801 context.previousNode = ast; 7802 } 7803 7804 visitGroup(ast, context) { 7805 const innerTimelines = []; 7806 let furthestTime = context.currentTimeline.currentTime; 7807 const delay = ast.options && ast.options.delay ? resolveTimingValue(ast.options.delay) : 0; 7808 ast.steps.forEach(s => { 7809 const innerContext = context.createSubContext(ast.options); 7810 7811 if (delay) { 7812 innerContext.delayNextStep(delay); 7813 } 7814 7815 visitDslNode(this, s, innerContext); 7816 furthestTime = Math.max(furthestTime, innerContext.currentTimeline.currentTime); 7817 innerTimelines.push(innerContext.currentTimeline); 7818 }); // this operation is run after the AST loop because otherwise 7819 // if the parent timeline's collected styles were updated then 7820 // it would pass in invalid data into the new-to-be forked items 7821 7822 innerTimelines.forEach(timeline => context.currentTimeline.mergeTimelineCollectedStyles(timeline)); 7823 context.transformIntoNewTimeline(furthestTime); 7824 context.previousNode = ast; 7825 } 7826 7827 _visitTiming(ast, context) { 7828 if (ast.dynamic) { 7829 const strValue = ast.strValue; 7830 const timingValue = context.params ? interpolateParams(strValue, context.params, context.errors) : strValue; 7831 return resolveTiming(timingValue, context.errors); 7832 } else { 7833 return { 7834 duration: ast.duration, 7835 delay: ast.delay, 7836 easing: ast.easing 7837 }; 7838 } 7839 } 7840 7841 visitAnimate(ast, context) { 7842 const timings = context.currentAnimateTimings = this._visitTiming(ast.timings, context); 7843 7844 const timeline = context.currentTimeline; 7845 7846 if (timings.delay) { 7847 context.incrementTime(timings.delay); 7848 timeline.snapshotCurrentStyles(); 7849 } 7850 7851 const style = ast.style; 7852 7853 if (style.type == 5 7854 /* AnimationMetadataType.Keyframes */ 7855 ) { 7856 this.visitKeyframes(style, context); 7857 } else { 7858 context.incrementTime(timings.duration); 7859 this.visitStyle(style, context); 7860 timeline.applyStylesToKeyframe(); 7861 } 7862 7863 context.currentAnimateTimings = null; 7864 context.previousNode = ast; 7865 } 7866 7867 visitStyle(ast, context) { 7868 const timeline = context.currentTimeline; 7869 const timings = context.currentAnimateTimings; // this is a special case for when a style() call 7870 // directly follows an animate() call (but not inside of an animate() call) 7871 7872 if (!timings && timeline.hasCurrentStyleProperties()) { 7873 timeline.forwardFrame(); 7874 } 7875 7876 const easing = timings && timings.easing || ast.easing; 7877 7878 if (ast.isEmptyStep) { 7879 timeline.applyEmptyStep(easing); 7880 } else { 7881 timeline.setStyles(ast.styles, easing, context.errors, context.options); 7882 } 7883 7884 context.previousNode = ast; 7885 } 7886 7887 visitKeyframes(ast, context) { 7888 const currentAnimateTimings = context.currentAnimateTimings; 7889 const startTime = context.currentTimeline.duration; 7890 const duration = currentAnimateTimings.duration; 7891 const innerContext = context.createSubContext(); 7892 const innerTimeline = innerContext.currentTimeline; 7893 innerTimeline.easing = currentAnimateTimings.easing; 7894 ast.styles.forEach(step => { 7895 const offset = step.offset || 0; 7896 innerTimeline.forwardTime(offset * duration); 7897 innerTimeline.setStyles(step.styles, step.easing, context.errors, context.options); 7898 innerTimeline.applyStylesToKeyframe(); 7899 }); // this will ensure that the parent timeline gets all the styles from 7900 // the child even if the new timeline below is not used 7901 7902 context.currentTimeline.mergeTimelineCollectedStyles(innerTimeline); // we do this because the window between this timeline and the sub timeline 7903 // should ensure that the styles within are exactly the same as they were before 7904 7905 context.transformIntoNewTimeline(startTime + duration); 7906 context.previousNode = ast; 7907 } 7908 7909 visitQuery(ast, context) { 7910 // in the event that the first step before this is a style step we need 7911 // to ensure the styles are applied before the children are animated 7912 const startTime = context.currentTimeline.currentTime; 7913 const options = ast.options || {}; 7914 const delay = options.delay ? resolveTimingValue(options.delay) : 0; 7915 7916 if (delay && (context.previousNode.type === 6 7917 /* AnimationMetadataType.Style */ 7918 || startTime == 0 && context.currentTimeline.hasCurrentStyleProperties())) { 7919 context.currentTimeline.snapshotCurrentStyles(); 7920 context.previousNode = DEFAULT_NOOP_PREVIOUS_NODE; 7921 } 7922 7923 let furthestTime = startTime; 7924 const elms = context.invokeQuery(ast.selector, ast.originalSelector, ast.limit, ast.includeSelf, options.optional ? true : false, context.errors); 7925 context.currentQueryTotal = elms.length; 7926 let sameElementTimeline = null; 7927 elms.forEach((element, i) => { 7928 context.currentQueryIndex = i; 7929 const innerContext = context.createSubContext(ast.options, element); 7930 7931 if (delay) { 7932 innerContext.delayNextStep(delay); 7933 } 7934 7935 if (element === context.element) { 7936 sameElementTimeline = innerContext.currentTimeline; 7937 } 7938 7939 visitDslNode(this, ast.animation, innerContext); // this is here just incase the inner steps only contain or end 7940 // with a style() call (which is here to signal that this is a preparatory 7941 // call to style an element before it is animated again) 7942 7943 innerContext.currentTimeline.applyStylesToKeyframe(); 7944 const endTime = innerContext.currentTimeline.currentTime; 7945 furthestTime = Math.max(furthestTime, endTime); 7946 }); 7947 context.currentQueryIndex = 0; 7948 context.currentQueryTotal = 0; 7949 context.transformIntoNewTimeline(furthestTime); 7950 7951 if (sameElementTimeline) { 7952 context.currentTimeline.mergeTimelineCollectedStyles(sameElementTimeline); 7953 context.currentTimeline.snapshotCurrentStyles(); 7954 } 7955 7956 context.previousNode = ast; 7957 } 7958 7959 visitStagger(ast, context) { 7960 const parentContext = context.parentContext; 7961 const tl = context.currentTimeline; 7962 const timings = ast.timings; 7963 const duration = Math.abs(timings.duration); 7964 const maxTime = duration * (context.currentQueryTotal - 1); 7965 let delay = duration * context.currentQueryIndex; 7966 let staggerTransformer = timings.duration < 0 ? 'reverse' : timings.easing; 7967 7968 switch (staggerTransformer) { 7969 case 'reverse': 7970 delay = maxTime - delay; 7971 break; 7972 7973 case 'full': 7974 delay = parentContext.currentStaggerTime; 7975 break; 7976 } 7977 7978 const timeline = context.currentTimeline; 7979 7980 if (delay) { 7981 timeline.delayNextStep(delay); 7982 } 7983 7984 const startingTime = timeline.currentTime; 7985 visitDslNode(this, ast.animation, context); 7986 context.previousNode = ast; // time = duration + delay 7987 // the reason why this computation is so complex is because 7988 // the inner timeline may either have a delay value or a stretched 7989 // keyframe depending on if a subtimeline is not used or is used. 7990 7991 parentContext.currentStaggerTime = tl.currentTime - startingTime + (tl.startTime - parentContext.currentTimeline.startTime); 7992 } 7993 7994} 7995 7996const DEFAULT_NOOP_PREVIOUS_NODE = {}; 7997 7998class AnimationTimelineContext { 7999 constructor(_driver, element, subInstructions, _enterClassName, _leaveClassName, errors, timelines, initialTimeline) { 8000 this._driver = _driver; 8001 this.element = element; 8002 this.subInstructions = subInstructions; 8003 this._enterClassName = _enterClassName; 8004 this._leaveClassName = _leaveClassName; 8005 this.errors = errors; 8006 this.timelines = timelines; 8007 this.parentContext = null; 8008 this.currentAnimateTimings = null; 8009 this.previousNode = DEFAULT_NOOP_PREVIOUS_NODE; 8010 this.subContextCount = 0; 8011 this.options = {}; 8012 this.currentQueryIndex = 0; 8013 this.currentQueryTotal = 0; 8014 this.currentStaggerTime = 0; 8015 this.currentTimeline = initialTimeline || new TimelineBuilder(this._driver, element, 0); 8016 timelines.push(this.currentTimeline); 8017 } 8018 8019 get params() { 8020 return this.options.params; 8021 } 8022 8023 updateOptions(options, skipIfExists) { 8024 if (!options) return; 8025 const newOptions = options; 8026 let optionsToUpdate = this.options; // NOTE: this will get patched up when other animation methods support duration overrides 8027 8028 if (newOptions.duration != null) { 8029 optionsToUpdate.duration = resolveTimingValue(newOptions.duration); 8030 } 8031 8032 if (newOptions.delay != null) { 8033 optionsToUpdate.delay = resolveTimingValue(newOptions.delay); 8034 } 8035 8036 const newParams = newOptions.params; 8037 8038 if (newParams) { 8039 let paramsToUpdate = optionsToUpdate.params; 8040 8041 if (!paramsToUpdate) { 8042 paramsToUpdate = this.options.params = {}; 8043 } 8044 8045 Object.keys(newParams).forEach(name => { 8046 if (!skipIfExists || !paramsToUpdate.hasOwnProperty(name)) { 8047 paramsToUpdate[name] = interpolateParams(newParams[name], paramsToUpdate, this.errors); 8048 } 8049 }); 8050 } 8051 } 8052 8053 _copyOptions() { 8054 const options = {}; 8055 8056 if (this.options) { 8057 const oldParams = this.options.params; 8058 8059 if (oldParams) { 8060 const params = options['params'] = {}; 8061 Object.keys(oldParams).forEach(name => { 8062 params[name] = oldParams[name]; 8063 }); 8064 } 8065 } 8066 8067 return options; 8068 } 8069 8070 createSubContext(options = null, element, newTime) { 8071 const target = element || this.element; 8072 const context = new AnimationTimelineContext(this._driver, target, this.subInstructions, this._enterClassName, this._leaveClassName, this.errors, this.timelines, this.currentTimeline.fork(target, newTime || 0)); 8073 context.previousNode = this.previousNode; 8074 context.currentAnimateTimings = this.currentAnimateTimings; 8075 context.options = this._copyOptions(); 8076 context.updateOptions(options); 8077 context.currentQueryIndex = this.currentQueryIndex; 8078 context.currentQueryTotal = this.currentQueryTotal; 8079 context.parentContext = this; 8080 this.subContextCount++; 8081 return context; 8082 } 8083 8084 transformIntoNewTimeline(newTime) { 8085 this.previousNode = DEFAULT_NOOP_PREVIOUS_NODE; 8086 this.currentTimeline = this.currentTimeline.fork(this.element, newTime); 8087 this.timelines.push(this.currentTimeline); 8088 return this.currentTimeline; 8089 } 8090 8091 appendInstructionToTimeline(instruction, duration, delay) { 8092 const updatedTimings = { 8093 duration: duration != null ? duration : instruction.duration, 8094 delay: this.currentTimeline.currentTime + (delay != null ? delay : 0) + instruction.delay, 8095 easing: '' 8096 }; 8097 const builder = new SubTimelineBuilder(this._driver, instruction.element, instruction.keyframes, instruction.preStyleProps, instruction.postStyleProps, updatedTimings, instruction.stretchStartingKeyframe); 8098 this.timelines.push(builder); 8099 return updatedTimings; 8100 } 8101 8102 incrementTime(time) { 8103 this.currentTimeline.forwardTime(this.currentTimeline.duration + time); 8104 } 8105 8106 delayNextStep(delay) { 8107 // negative delays are not yet supported 8108 if (delay > 0) { 8109 this.currentTimeline.delayNextStep(delay); 8110 } 8111 } 8112 8113 invokeQuery(selector, originalSelector, limit, includeSelf, optional, errors) { 8114 let results = []; 8115 8116 if (includeSelf) { 8117 results.push(this.element); 8118 } 8119 8120 if (selector.length > 0) { 8121 // only if :self is used then the selector can be empty 8122 selector = selector.replace(ENTER_TOKEN_REGEX, '.' + this._enterClassName); 8123 selector = selector.replace(LEAVE_TOKEN_REGEX, '.' + this._leaveClassName); 8124 const multi = limit != 1; 8125 8126 let elements = this._driver.query(this.element, selector, multi); 8127 8128 if (limit !== 0) { 8129 elements = limit < 0 ? elements.slice(elements.length + limit, elements.length) : elements.slice(0, limit); 8130 } 8131 8132 results.push(...elements); 8133 } 8134 8135 if (!optional && results.length == 0) { 8136 errors.push(invalidQuery(originalSelector)); 8137 } 8138 8139 return results; 8140 } 8141 8142} 8143 8144class TimelineBuilder { 8145 constructor(_driver, element, startTime, _elementTimelineStylesLookup) { 8146 this._driver = _driver; 8147 this.element = element; 8148 this.startTime = startTime; 8149 this._elementTimelineStylesLookup = _elementTimelineStylesLookup; 8150 this.duration = 0; 8151 this._previousKeyframe = new Map(); 8152 this._currentKeyframe = new Map(); 8153 this._keyframes = new Map(); 8154 this._styleSummary = new Map(); 8155 this._localTimelineStyles = new Map(); 8156 this._pendingStyles = new Map(); 8157 this._backFill = new Map(); 8158 this._currentEmptyStepKeyframe = null; 8159 8160 if (!this._elementTimelineStylesLookup) { 8161 this._elementTimelineStylesLookup = new Map(); 8162 } 8163 8164 this._globalTimelineStyles = this._elementTimelineStylesLookup.get(element); 8165 8166 if (!this._globalTimelineStyles) { 8167 this._globalTimelineStyles = this._localTimelineStyles; 8168 8169 this._elementTimelineStylesLookup.set(element, this._localTimelineStyles); 8170 } 8171 8172 this._loadKeyframe(); 8173 } 8174 8175 containsAnimation() { 8176 switch (this._keyframes.size) { 8177 case 0: 8178 return false; 8179 8180 case 1: 8181 return this.hasCurrentStyleProperties(); 8182 8183 default: 8184 return true; 8185 } 8186 } 8187 8188 hasCurrentStyleProperties() { 8189 return this._currentKeyframe.size > 0; 8190 } 8191 8192 get currentTime() { 8193 return this.startTime + this.duration; 8194 } 8195 8196 delayNextStep(delay) { 8197 // in the event that a style() step is placed right before a stagger() 8198 // and that style() step is the very first style() value in the animation 8199 // then we need to make a copy of the keyframe [0, copy, 1] so that the delay 8200 // properly applies the style() values to work with the stagger... 8201 const hasPreStyleStep = this._keyframes.size === 1 && this._pendingStyles.size; 8202 8203 if (this.duration || hasPreStyleStep) { 8204 this.forwardTime(this.currentTime + delay); 8205 8206 if (hasPreStyleStep) { 8207 this.snapshotCurrentStyles(); 8208 } 8209 } else { 8210 this.startTime += delay; 8211 } 8212 } 8213 8214 fork(element, currentTime) { 8215 this.applyStylesToKeyframe(); 8216 return new TimelineBuilder(this._driver, element, currentTime || this.currentTime, this._elementTimelineStylesLookup); 8217 } 8218 8219 _loadKeyframe() { 8220 if (this._currentKeyframe) { 8221 this._previousKeyframe = this._currentKeyframe; 8222 } 8223 8224 this._currentKeyframe = this._keyframes.get(this.duration); 8225 8226 if (!this._currentKeyframe) { 8227 this._currentKeyframe = new Map(); 8228 8229 this._keyframes.set(this.duration, this._currentKeyframe); 8230 } 8231 } 8232 8233 forwardFrame() { 8234 this.duration += ONE_FRAME_IN_MILLISECONDS; 8235 8236 this._loadKeyframe(); 8237 } 8238 8239 forwardTime(time) { 8240 this.applyStylesToKeyframe(); 8241 this.duration = time; 8242 8243 this._loadKeyframe(); 8244 } 8245 8246 _updateStyle(prop, value) { 8247 this._localTimelineStyles.set(prop, value); 8248 8249 this._globalTimelineStyles.set(prop, value); 8250 8251 this._styleSummary.set(prop, { 8252 time: this.currentTime, 8253 value 8254 }); 8255 } 8256 8257 allowOnlyTimelineStyles() { 8258 return this._currentEmptyStepKeyframe !== this._currentKeyframe; 8259 } 8260 8261 applyEmptyStep(easing) { 8262 if (easing) { 8263 this._previousKeyframe.set('easing', easing); 8264 } // special case for animate(duration): 8265 // all missing styles are filled with a `*` value then 8266 // if any destination styles are filled in later on the same 8267 // keyframe then they will override the overridden styles 8268 // We use `_globalTimelineStyles` here because there may be 8269 // styles in previous keyframes that are not present in this timeline 8270 8271 8272 for (let [prop, value] of this._globalTimelineStyles) { 8273 this._backFill.set(prop, value || _angular_animations__WEBPACK_IMPORTED_MODULE_1__.AUTO_STYLE); 8274 8275 this._currentKeyframe.set(prop, _angular_animations__WEBPACK_IMPORTED_MODULE_1__.AUTO_STYLE); 8276 } 8277 8278 this._currentEmptyStepKeyframe = this._currentKeyframe; 8279 } 8280 8281 setStyles(input, easing, errors, options) { 8282 if (easing) { 8283 this._previousKeyframe.set('easing', easing); 8284 } 8285 8286 const params = options && options.params || {}; 8287 const styles = flattenStyles(input, this._globalTimelineStyles); 8288 8289 for (let [prop, value] of styles) { 8290 const val = interpolateParams(value, params, errors); 8291 8292 this._pendingStyles.set(prop, val); 8293 8294 if (!this._localTimelineStyles.has(prop)) { 8295 this._backFill.set(prop, this._globalTimelineStyles.get(prop) ?? _angular_animations__WEBPACK_IMPORTED_MODULE_1__.AUTO_STYLE); 8296 } 8297 8298 this._updateStyle(prop, val); 8299 } 8300 } 8301 8302 applyStylesToKeyframe() { 8303 if (this._pendingStyles.size == 0) return; 8304 8305 this._pendingStyles.forEach((val, prop) => { 8306 this._currentKeyframe.set(prop, val); 8307 }); 8308 8309 this._pendingStyles.clear(); 8310 8311 this._localTimelineStyles.forEach((val, prop) => { 8312 if (!this._currentKeyframe.has(prop)) { 8313 this._currentKeyframe.set(prop, val); 8314 } 8315 }); 8316 } 8317 8318 snapshotCurrentStyles() { 8319 for (let [prop, val] of this._localTimelineStyles) { 8320 this._pendingStyles.set(prop, val); 8321 8322 this._updateStyle(prop, val); 8323 } 8324 } 8325 8326 getFinalKeyframe() { 8327 return this._keyframes.get(this.duration); 8328 } 8329 8330 get properties() { 8331 const properties = []; 8332 8333 for (let prop in this._currentKeyframe) { 8334 properties.push(prop); 8335 } 8336 8337 return properties; 8338 } 8339 8340 mergeTimelineCollectedStyles(timeline) {
8341 timeline._styleSummary.forEach((details1, prop) => { 8342 const details0 = this._styleSummary.get(prop); 8343 8344 if (!details0 || details1.time > details0.time) { 8345 this._updateStyle(prop, details1.value); 8346 } 8347 }); 8348 } 8349 8350 buildKeyframes() { 8351 this.applyStylesToKeyframe(); 8352 const preStyleProps = new Set(); 8353 const postStyleProps = new Set(); 8354 const isEmpty = this._keyframes.size === 1 && this.duration === 0; 8355 let finalKeyframes = []; 8356 8357 this._keyframes.forEach((keyframe, time) => { 8358 const finalKeyframe = copyStyles(keyframe, new Map(), this._backFill); 8359 finalKeyframe.forEach((value, prop) => { 8360 if (value === _angular_animations__WEBPACK_IMPORTED_MODULE_1__["ɵPRE_STYLE"]) { 8361 preStyleProps.add(prop); 8362 } else if (value === _angular_animations__WEBPACK_IMPORTED_MODULE_1__.AUTO_STYLE) { 8363 postStyleProps.add(prop); 8364 } 8365 }); 8366 8367 if (!isEmpty) { 8368 finalKeyframe.set('offset', time / this.duration); 8369 } 8370 8371 finalKeyframes.push(finalKeyframe); 8372 }); 8373 8374 const preProps = preStyleProps.size ? iteratorToArray(preStyleProps.values()) : []; 8375 const postProps = postStyleProps.size ? iteratorToArray(postStyleProps.values()) : []; // special case for a 0-second animation (which is designed just to place styles onscreen) 8376 8377 if (isEmpty) { 8378 const kf0 = finalKeyframes[0]; 8379 const kf1 = new Map(kf0); 8380 kf0.set('offset', 0); 8381 kf1.set('offset', 1); 8382 finalKeyframes = [kf0, kf1]; 8383 } 8384
vendor: 2,684 bytes, lines 8385-8456
8385 return createTimelineInstruction(this.element, finalKeyframes, preProps, postProps, this.duration, this.startTime, this.easing, false); 8386 } 8387 8388} 8389 8390class SubTimelineBuilder extends TimelineBuilder { 8391 constructor(driver, element, keyframes, preStyleProps, postStyleProps, timings, _stretchStartingKeyframe = false) { 8392 super(driver, element, timings.delay); 8393 this.keyframes = keyframes; 8394 this.preStyleProps = preStyleProps; 8395 this.postStyleProps = postStyleProps; 8396 this._stretchStartingKeyframe = _stretchStartingKeyframe; 8397 this.timings = { 8398 duration: timings.duration, 8399 delay: timings.delay, 8400 easing: timings.easing 8401 }; 8402 } 8403 8404 containsAnimation() { 8405 return this.keyframes.length > 1; 8406 } 8407 8408 buildKeyframes() { 8409 let keyframes = this.keyframes; 8410 let { 8411 delay, 8412 duration, 8413 easing 8414 } = this.timings; 8415 8416 if (this._stretchStartingKeyframe && delay) { 8417 const newKeyframes = []; 8418 const totalTime = duration + delay; 8419 const startingGap = delay / totalTime; // the original starting keyframe now starts once the delay is done 8420 8421 const newFirstKeyframe = copyStyles(keyframes[0]); 8422 newFirstKeyframe.set('offset', 0); 8423 newKeyframes.push(newFirstKeyframe); 8424 const oldFirstKeyframe = copyStyles(keyframes[0]); 8425 oldFirstKeyframe.set('offset', roundOffset(startingGap)); 8426 newKeyframes.push(oldFirstKeyframe); 8427 /* 8428 When the keyframe is stretched then it means that the delay before the animation 8429 starts is gone. Instead the first keyframe is placed at the start of the animation 8430 and it is then copied to where it starts when the original delay is over. This basically 8431 means nothing animates during that delay, but the styles are still rendered. For this 8432 to work the original offset values that exist in the original keyframes must be "warped" 8433 so that they can take the new keyframe + delay into account. 8434 delay=1000, duration=1000, keyframes = 0 .5 1 8435 turns into 8436 delay=0, duration=2000, keyframes = 0 .33 .66 1 8437 */ 8438 // offsets between 1 ... n -1 are all warped by the keyframe stretch 8439 8440 const limit = keyframes.length - 1; 8441 8442 for (let i = 1; i <= limit; i++) { 8443 let kf = copyStyles(keyframes[i]); 8444 const oldOffset = kf.get('offset'); 8445 const timeAtKeyframe = delay + oldOffset * duration; 8446 kf.set('offset', roundOffset(timeAtKeyframe / totalTime)); 8447 newKeyframes.push(kf); 8448 } // the new starting keyframe should be added at the start 8449 8450 8451 duration = totalTime; 8452 delay = 0; 8453 easing = ''; 8454 keyframes = newKeyframes; 8455 } 8456
8457 return createTimelineInstruction(this.element, keyframes, this.preStyleProps, this.postStyleProps, duration, delay, easing, true); 8458 } 8459 8460} 8461 8462function roundOffset(offset, decimalPoints = 3) { 8463 const mult = Math.pow(10, decimalPoints - 1); 8464 return Math.round(offset * mult) / mult; 8465} 8466 8467function flattenStyles(input, allStyles) { 8468 const styles = new Map(); 8469 let allProperties; 8470 input.forEach(token => { 8471 if (token === '*') { 8472 allProperties = allProperties || allStyles.keys(); 8473 8474 for (let prop of allProperties) { 8475 styles.set(prop, _angular_animations__WEBPACK_IMPORTED_MODULE_1__.AUTO_STYLE); 8476 } 8477 } else { 8478 copyStyles(token, styles); 8479 } 8480 }); 8481 return styles; 8482} 8483 8484class Animation { 8485 constructor(_driver, input) { 8486 this._driver = _driver; 8487 const errors = []; 8488 const warnings = []; 8489 const ast = buildAnimationAst(_driver, input, errors, warnings); 8490 8491 if (errors.length) { 8492 throw validationFailed(errors); 8493 } 8494 8495 if (warnings.length) { 8496 warnValidation(warnings); 8497 } 8498 8499 this._animationAst = ast; 8500 } 8501 8502 buildTimelines(element, startingStyles, destinationStyles, options, subInstructions) { 8503 const start = Array.isArray(startingStyles) ? normalizeStyles(startingStyles) : startingStyles; 8504 const dest = Array.isArray(destinationStyles) ? normalizeStyles(destinationStyles) : destinationStyles; 8505 const errors = []; 8506 subInstructions = subInstructions || new ElementInstructionMap(); 8507 const result = buildAnimationTimelines(this._driver, element, this._animationAst, ENTER_CLASSNAME, LEAVE_CLASSNAME, start, dest, options, subInstructions, errors); 8508 8509 if (errors.length) { 8510 throw buildingFailed(errors); 8511 } 8512 8513 return result; 8514 } 8515 8516} 8517/** 8518 * @license 8519 * Copyright Google LLC All Rights Reserved. 8520 * 8521 * Use of this source code is governed by an MIT-style license that can be 8522 * found in the LICENSE file at https://angular.io/license 8523 */ 8524 8525/** 8526 * @publicApi 8527 */ 8528 8529 8530class AnimationStyleNormalizer {} 8531/** 8532 * @publicApi 8533 */ 8534 8535 8536class NoopAnimationStyleNormalizer { 8537 normalizePropertyName(propertyName, errors) { 8538 return propertyName; 8539 } 8540 8541 normalizeStyleValue(userProvidedProperty, normalizedProperty, value, errors) { 8542 return value; 8543 } 8544 8545} 8546/** 8547 * @license 8548 * Copyright Google LLC All Rights Reserved. 8549 * 8550 * Use of this source code is governed by an MIT-style license that can be 8551 * found in the LICENSE file at https://angular.io/license 8552 */ 8553 8554 8555const DIMENSIONAL_PROP_SET = new Set(['width', 'height', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight', 'left', 'top', 'bottom', 'right', 'fontSize', 'outlineWidth', 'outlineOffset', 'paddingTop', 'paddingLeft', 'paddingBottom', 'paddingRight', 'marginTop', 'marginLeft', 'marginBottom', 'marginRight', 'borderRadius', 'borderWidth', 'borderTopWidth', 'borderLeftWidth', 'borderRightWidth', 'borderBottomWidth', 'textIndent', 'perspective']); 8556 8557class WebAnimationsStyleNormalizer extends AnimationStyleNormalizer { 8558 normalizePropertyName(propertyName, errors) { 8559 return dashCaseToCamelCase(propertyName); 8560 } 8561 8562 normalizeStyleValue(userProvidedProperty, normalizedProperty, value, errors) { 8563 let unit = ''; 8564 const strVal = value.toString().trim(); 8565 8566 if (DIMENSIONAL_PROP_SET.has(normalizedProperty) && value !== 0 && value !== '0') { 8567 if (typeof value === 'number') { 8568 unit = 'px'; 8569 } else { 8570 const valAndSuffixMatch = value.match(/^[+-]?[\d\.]+([a-z]*)$/); 8571 8572 if (valAndSuffixMatch && valAndSuffixMatch[1].length == 0) { 8573 errors.push(invalidCssUnitValue(userProvidedProperty, value)); 8574 } 8575 } 8576 } 8577 8578 return strVal + unit; 8579 } 8580 8581} 8582/** 8583 * @license 8584 * Copyright Google LLC All Rights Reserved. 8585 * 8586 * Use of this source code is governed by an MIT-style license that can be 8587 * found in the LICENSE file at https://angular.io/license 8588 */ 8589 8590 8591function createTransitionInstruction(element, triggerName, fromState, toState, isRemovalTransition, fromStyles, toStyles, timelines, queriedElements, preStyleProps, postStyleProps, totalTime, errors) { 8592 return { 8593 type: 0 8594 /* AnimationTransitionInstructionType.TransitionAnimation */ 8595 , 8596 element, 8597 triggerName, 8598 isRemovalTransition, 8599 fromState, 8600 fromStyles, 8601 toState, 8602 toStyles, 8603 timelines, 8604 queriedElements, 8605 preStyleProps, 8606 postStyleProps, 8607 totalTime, 8608 errors 8609 }; 8610} 8611 8612const EMPTY_OBJECT = {}; 8613 8614class AnimationTransitionFactory { 8615 constructor(_triggerName, ast, _stateStyles) { 8616 this._triggerName = _triggerName; 8617 this.ast = ast; 8618 this._stateStyles = _stateStyles; 8619 } 8620 8621 match(currentState, nextState, element, params) { 8622 return oneOrMoreTransitionsMatch(this.ast.matchers, currentState, nextState, element, params); 8623 } 8624 8625 buildStyles(stateName, params, errors) { 8626 let styler = this._stateStyles.get('*'); 8627 8628 if (stateName !== undefined) { 8629 styler = this._stateStyles.get(stateName?.toString()) || styler; 8630 } 8631 8632 return styler ? styler.buildStyles(params, errors) : new Map(); 8633 } 8634 8635 build(driver, element, currentState, nextState, enterClassName, leaveClassName, currentOptions, nextOptions, subInstru
8635ctions, skipAstBuild) { 8636 const errors = []; 8637 const transitionAnimationParams = this.ast.options && this.ast.options.params || EMPTY_OBJECT; 8638 const currentAnimationParams = currentOptions && currentOptions.params || EMPTY_OBJECT; 8639 const currentStateStyles = this.buildStyles(currentState, currentAnimationParams, errors); 8640 const nextAnimationParams = nextOptions && nextOptions.params || EMPTY_OBJECT; 8641 const nextStateStyles = this.buildStyles(nextState, nextAnimationParams, errors); 8642 const queriedElements = new Set(); 8643 const preStyleMap = new Map(); 8644 const postStyleMap = new Map(); 8645 const isRemoval = nextState === 'void'; 8646 const animationOptions = { 8647 params: applyParamDefaults(nextAnimationParams, transitionAnimationParams), 8648 delay: this.ast.options?.delay 8649 }; 8650 const timelines = skipAstBuild ? [] : buildAnimationTimelines(driver, element, this.ast.animation, enterClassName, leaveClassName, currentStateStyles, nextStateStyles, animationOptions, subInstructions, errors); 8651 let totalTime = 0; 8652 timelines.forEach(tl => { 8653 totalTime = Math.max(tl.duration + tl.delay, totalTime); 8654 }); 8655 8656 if (errors.length) { 8657 return createTransitionInstruction(element, this._triggerName, currentState, nextState, isRemoval, currentStateStyles, nextStateStyles, [], [], preStyleMap, postStyleMap, totalTime, errors); 8658 } 8659 8660 timelines.forEach(tl => { 8661 const elm = tl.element; 8662 const preProps = getOrSetDefaultValue(preStyleMap, elm, new Set()); 8663 tl.preStyleProps.forEach(prop => preProps.add(prop)); 8664 const postProps = getOrSetDefaultValue(postStyleMap, elm, new Set()); 8665 tl.postStyleProps.forEach(prop => postProps.add(prop)); 8666 8667 if (elm !== element) { 8668 queriedElements.add(elm); 8669 } 8670 }); 8671 8672 if (typeof ngDevMode === 'undefined' || ngDevMode) { 8673 checkNonAnimatableInTimelines(timelines, this._triggerName, driver); 8674 } 8675 8676 const queriedElementsList = iteratorToArray(queriedElements.values()); 8677 return createTransitionInstruction(element, this._triggerName, currentState, nextState, isRemoval, currentStateStyles, nextStateStyles, timelines, queriedElementsList, preStyleMap, postStyleMap, totalTime); 8678 } 8679 8680} 8681/** 8682 * Checks inside a set of timelines if they try to animate a css property which is not considered 8683 * animatable, in that case it prints a warning on the console. 8684 * Besides that the function doesn't have any other effect. 8685 * 8686 * Note: this check is done here after the timelines are built instead of doing on a lower level so 8687 * that we can make sure that the warning appears only once per instruction (we can aggregate here 8688 * all the issues instead of finding them separately). 8689 * 8690 * @param timelines The built timelines for the current instruction. 8691 * @param triggerName The name of the trigger for the current instruction. 8692 * @param driver Animation driver used to perform the check. 8693 * 8694 */ 8695 8696 8697function checkNonAnimatableInTimelines(timelines, triggerName, driver) { 8698 if (!driver.validateAnimatableStyleProperty) { 8699 return; 8700 } 8701 8702 const invalidNonAnimatableProps = new Set(); 8703 timelines.forEach(({ 8704 keyframes 8705 }) => { 8706 const nonAnimatablePropsInitialValues = new Map(); 8707 keyframes.forEach(keyframe => { 8708 for (const [prop, value] of keyframe.entries()) { 8709 if (!driver.validateAnimatableStyleProperty(prop)) { 8710 if (nonAnimatablePropsInitialValues.has(prop) && !invalidNonAnimatableProps.has(prop)) { 8711 const propInitialValue = nonAnimatablePropsInitialValues.get(prop); 8712 8713 if (propInitialValue !== value) { 8714 invalidNonAnimatableProps.add(prop); 8715 } 8716 } else { 8717 nonAnimatablePropsInitialValues.set(prop, value); 8718 } 8719 } 8720 } 8721 }); 8722 }); 8723 8724 if (invalidNonAnimatableProps.size > 0) { 8725 console.warn(`Warning: The animation trigger "${triggerName}" is attempting to animate the following` + ' not animatable properties: ' + Array.from(invalidNonAnimatableProps).join(', ') + '\n' + '(to check the list of all animatable properties visit https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties)'); 8726 } 8727} 8728 8729function oneOrMoreTransitionsMatch(matchFns, currentState, nextState, element, params) { 8730 return matchFns.some(fn => fn(currentState, nextState, element, params)); 8731} 8732 8733function applyParamDefaults(userParams, defaults) { 8734 const result = copyObj(defaults); 8735 8736 for (const key in userParams) { 8737 if (userParams.hasOwnProperty(key) && userParams[key] != null) { 8738 result[key] = userParams[key]; 8739 } 8740 } 8741 8742 return result; 8743} 8744 8745class AnimationStateStyles { 8746 constructor(styles, defaultParams, normalizer) { 8747 this.styles = styles; 8748 this.defaultParams = defaultParams; 8749 this.normalizer = normalizer; 8750 } 8751 8752 buildStyles(params, errors) { 8753 const finalStyles = new Map(); 8754 const combinedParams = copyObj(this.defaultParams);
8755 Object.keys(params).forEach(key => { 8756 const value = params[key]; 8757 8758 if (value !== null) { 8759 combinedParams[key] = value; 8760 } 8761 }); 8762 this.styles.styles.forEach(value => { 8763 if (typeof value !== 'string') { 8764 value.forEach((val, prop) => { 8765 if (val) { 8766 val = interpolateParams(val, combinedParams, errors); 8767 } 8768 8769 const normalizedProp = this.normalizer.normalizePropertyName(prop, errors); 8770 val = this.normalizer.normalizeStyleValue(prop, normalizedProp, val, errors); 8771 finalStyles.set(normalizedProp, val); 8772 }); 8773 } 8774 }); 8775 return finalStyles; 8776 } 8777 8778} 8779 8780function buildTrigger(name, ast, normalizer) { 8781 return new AnimationTrigger(name, ast, normalizer); 8782} 8783 8784class AnimationTrigger { 8785 constructor(name, ast, _normalizer) { 8786 this.name = name; 8787 this.ast = ast; 8788 this._normalizer = _normalizer; 8789 this.transitionFactories = []; 8790 this.states = new Map(); 8791 ast.states.forEach(ast => { 8792 const defaultParams = ast.options && ast.options.params || {}; 8793 this.states.set(ast.name, new AnimationStateStyles(ast.style, defaultParams, _normalizer)); 8794 }); 8795 balanceProperties(this.states, 'true', '1'); 8796 balanceProperties(this.states, 'false', '0'); 8797 ast.transitions.forEach(ast => { 8798 this.transitionFactories.push(new AnimationTransitionFactory(name, ast, this.states)); 8799 }); 8800 this.fallbackTransition = createFallbackTransition(name, this.states, this._normalizer); 8801 } 8802 8803 get containsQueries() { 8804 return this.ast.queryCount > 0; 8805 } 8806 8807 matchTransition(currentState, nextState, element, params) { 8808 const entry = this.transitionFactories.find(f => f.match(currentState, nextState, element, params)); 8809 return entry || null; 8810 } 8811 8812 matchStyles(currentState, params, errors) { 8813 return this.fallbackTransition.buildStyles(currentState, params, errors); 8814 } 8815 8816} 8817 8818function createFallbackTransition(triggerName, states, normalizer) { 8819 const matchers = [(fromState, toState) => true]; 8820 const animation = { 8821 type: 2 8822 /* AnimationMetadataType.Sequence */ 8823 , 8824 steps: [], 8825 options: null 8826 }; 8827 const transition = { 8828 type: 1 8829 /* AnimationMetadataType.Transition */ 8830 , 8831 animation, 8832 matchers, 8833 options: null, 8834 queryCount: 0, 8835 depCount: 0 8836 }; 8837 return new AnimationTransitionFactory(triggerName, transition, states); 8838} 8839 8840function balanceProperties(stateMap, key1, key2) { 8841 if (stateMap.has(key1)) { 8842 if (!stateMap.has(key2)) { 8843 stateMap.set(key2, stateMap.get(key1)); 8844 } 8845 } else if (stateMap.has(key2)) { 8846 stateMap.set(key1, stateMap.get(key2)); 8847 } 8848} 8849/** 8850 * @license 8851 * Copyright Google LLC All Rights Reserved. 8852 * 8853 * Use of this source code is governed by an MIT-style license that can be 8854 * found in the LICENSE file at https://angular.io/license 8855 */ 8856 8857 8858const EMPTY_INSTRUCTION_MAP = new ElementInstructionMap(); 8859 8860class TimelineAnimationEngine { 8861 constructor(bodyNode, _driver, _normalizer) { 8862 this.bodyNode = bodyNode; 8863 this._driver = _driver; 8864 this._normalizer = _normalizer; 8865 this._animations = new Map(); 8866 this._playersById = new Map(); 8867 this.players = []; 8868 } 8869 8870 register(id, metadata) { 8871 const errors = []; 8872 const warnings = []; 8873 const ast = buildAnimationAst(this._driver, metadata, errors, warnings); 8874 8875 if (errors.length) { 8876 throw registerFailed(errors); 8877 } else { 8878 if (warnings.length) { 8879 warnRegister(warnings); 8880 } 8881 8882 this._animations.set(id, ast); 8883 } 8884 } 8885 8886 _buildPlayer(i, preStyles, postStyles) { 8887 const element = i.element; 8888 const keyframes = normalizeKeyframes$1(this._driver, this._normalizer, element, i.keyframes, preStyles, postStyles); 8889 return this._driver.animate(element, keyframes, i.duration, i.delay, i.easing, [], true); 8890 } 8891 8892 create(id, element, options = {}) { 8893 const errors = []; 8894 8895 const ast = this._animations.get(id); 8896 8897 let instructions; 8898 const autoStylesMap = new Map(); 8899 8900 if (ast) { 8901 instructions = buildAnimationTimelines(this._driver, element, ast, ENTER_CLASSNAME, LEAVE_CLASSNAME, new Map(), new Map(), options, EMPTY_INSTRUCTION_MAP, errors); 8902 instructions.forEach(inst => { 8903 const styles = getOrSetDefaultValue(autoStylesMap, inst.element, new Map()); 8904 inst.postStyleProps.forEach(prop => styles.set(prop, null)); 8905 }); 8906 } else { 8907 errors.push(missingOrDestroyedAnimation()); 8908 instructions = []; 8909 } 8910 8911 if (errors.length) { 8912 throw createAnimationFailed(errors); 8913 } 8914
vendor: 17,520 bytes, lines 8915-9511
8915 autoStylesMap.forEach((styles, element) => { 8916 styles.forEach((_, prop) => { 8917 styles.set(prop, this._driver.computeStyle(element, prop, _angular_animations__WEBPACK_IMPORTED_MODULE_1__.AUTO_STYLE)); 8918 }); 8919 }); 8920 const players = instructions.map(i => { 8921 const styles = autoStylesMap.get(i.element); 8922 return this._buildPlayer(i, new Map(), styles); 8923 }); 8924 const player = optimizeGroupPlayer(players); 8925 8926 this._playersById.set(id, player); 8927 8928 player.onDestroy(() => this.destroy(id)); 8929 this.players.push(player); 8930 return player; 8931 } 8932 8933 destroy(id) { 8934 const player = this._getPlayer(id); 8935 8936 player.destroy(); 8937 8938 this._playersById.delete(id); 8939 8940 const index = this.players.indexOf(player); 8941 8942 if (index >= 0) { 8943 this.players.splice(index, 1); 8944 } 8945 } 8946 8947 _getPlayer(id) { 8948 const player = this._playersById.get(id); 8949 8950 if (!player) { 8951 throw missingPlayer(id); 8952 } 8953 8954 return player; 8955 } 8956 8957 listen(id, element, eventName, callback) { 8958 // triggerName, fromState, toState are all ignored for timeline animations 8959 const baseEvent = makeAnimationEvent(element, '', '', ''); 8960 listenOnPlayer(this._getPlayer(id), eventName, baseEvent, callback); 8961 return () => {}; 8962 } 8963 8964 command(id, element, command, args) { 8965 if (command == 'register') { 8966 this.register(id, args[0]); 8967 return; 8968 } 8969 8970 if (command == 'create') { 8971 const options = args[0] || {}; 8972 this.create(id, element, options); 8973 return; 8974 } 8975 8976 const player = this._getPlayer(id); 8977 8978 switch (command) { 8979 case 'play': 8980 player.play(); 8981 break; 8982 8983 case 'pause': 8984 player.pause(); 8985 break; 8986 8987 case 'reset': 8988 player.reset(); 8989 break; 8990 8991 case 'restart': 8992 player.restart(); 8993 break; 8994 8995 case 'finish': 8996 player.finish(); 8997 break; 8998 8999 case 'init': 9000 player.init(); 9001 break; 9002 9003 case 'setPosition': 9004 player.setPosition(parseFloat(args[0])); 9005 break; 9006 9007 case 'destroy': 9008 this.destroy(id); 9009 break; 9010 } 9011 } 9012 9013} 9014/** 9015 * @license 9016 * Copyright Google LLC All Rights Reserved. 9017 * 9018 * Use of this source code is governed by an MIT-style license that can be 9019 * found in the LICENSE file at https://angular.io/license 9020 */ 9021 9022 9023const QUEUED_CLASSNAME = 'ng-animate-queued'; 9024const QUEUED_SELECTOR = '.ng-animate-queued'; 9025const DISABLED_CLASSNAME = 'ng-animate-disabled'; 9026const DISABLED_SELECTOR = '.ng-animate-disabled'; 9027const STAR_CLASSNAME = 'ng-star-inserted'; 9028const STAR_SELECTOR = '.ng-star-inserted'; 9029const EMPTY_PLAYER_ARRAY = []; 9030const NULL_REMOVAL_STATE = { 9031 namespaceId: '', 9032 setForRemoval: false, 9033 setForMove: false, 9034 hasAnimation: false, 9035 removedBeforeQueried: false 9036}; 9037const NULL_REMOVED_QUERIED_STATE = { 9038 namespaceId: '', 9039 setForMove: false, 9040 setForRemoval: false, 9041 hasAnimation: false, 9042 removedBeforeQueried: true 9043}; 9044const REMOVAL_FLAG = '__ng_removed'; 9045 9046class StateValue { 9047 constructor(input, namespaceId = '') { 9048 this.namespaceId = namespaceId; 9049 const isObj = input && input.hasOwnProperty('value'); 9050 const value = isObj ? input['value'] : input; 9051 this.value = normalizeTriggerValue(value); 9052 9053 if (isObj) { 9054 const options = copyObj(input); 9055 delete options['value']; 9056 this.options = options; 9057 } else { 9058 this.options = {}; 9059 } 9060 9061 if (!this.options.params) { 9062 this.options.params = {}; 9063 } 9064 } 9065 9066 get params() { 9067 return this.options.params; 9068 } 9069 9070 absorbOptions(options) { 9071 const newParams = options.params; 9072 9073 if (newParams) { 9074 const oldParams = this.options.params; 9075 Object.keys(newParams).forEach(prop => { 9076 if (oldParams[prop] == null) { 9077 oldParams[prop] = newParams[prop]; 9078 } 9079 }); 9080 } 9081 } 9082 9083} 9084 9085const VOID_VALUE = 'void'; 9086const DEFAULT_STATE_VALUE = new StateValue(VOID_VALUE); 9087 9088class AnimationTransitionNamespace { 9089 constructor(id, hostElement, _engine) { 9090 this.id = id; 9091 this.hostElement = hostElement; 9092 this._engine = _engine; 9093 this.players = []; 9094 this._triggers = new Map(); 9095 this._queue = []; 9096 this._elementListeners = new Map(); 9097 this._hostClassName = 'ng-tns-' + id; 9098 addClass(hostElement, this._hostClassName); 9099 } 9100 9101 listen(element, name, phase, callback) { 9102 if (!this._triggers.has(name)) { 9103 throw missingTrigger(phase, name); 9104 } 9105 9106 if (phase == null || phase.length == 0) { 9107 throw missingEvent(name); 9108 } 9109 9110 if (!isTriggerEventValid(phase)) { 9111 throw unsupportedTriggerEvent(phase, name); 9112 } 9113 9114 const listeners = getOrSetDefaultValue(this._elementListeners, element, []); 9115 const data = { 9116 name, 9117 phase, 9118 callback 9119 }; 9120 listeners.push(data); 9121 const triggersWithStates = getOrSetDefaultValue(this._engine.statesByElement, element, new Map()); 9122 9123 if (!triggersWithStates.has(name)) { 9124 addClass(element, NG_TRIGGER_CLASSNAME); 9125 addClass(element, NG_TRIGGER_CLASSNAME + '-' + name); 9126 triggersWithStates.set(name, DEFAULT_STATE_VALUE); 9127 } 9128 9129 return () => { 9130 // the event listener is removed AFTER the flush has occurred such 9131 // that leave animations callbacks can fire (otherwise if the node 9132 // is removed in between then the listeners would be deregistered) 9133 this._engine.afterFlush(() => { 9134 const index = listeners.indexOf(data); 9135 9136 if (index >= 0) { 9137 listeners.splice(index, 1); 9138 } 9139 9140 if (!this._triggers.has(name)) { 9141 triggersWithStates.delete(name); 9142 } 9143 }); 9144 }; 9145 } 9146 9147 register(name, ast) { 9148 if (this._triggers.has(name)) { 9149 // throw 9150 return false; 9151 } else { 9152 this._triggers.set(name, ast); 9153 9154 return true; 9155 } 9156 } 9157 9158 _getTrigger(name) { 9159 const trigger = this._triggers.get(name); 9160 9161 if (!trigger) { 9162 throw unregisteredTrigger(name); 9163 } 9164 9165 return trigger; 9166 } 9167 9168 trigger(element, triggerName, value, defaultToFallback = true) { 9169 const trigger = this._getTrigger(triggerName); 9170 9171 const player = new TransitionAnimationPlayer(this.id, triggerName, element); 9172 9173 let triggersWithStates = this._engine.statesByElement.get(element); 9174 9175 if (!triggersWithStates) { 9176 addClass(element, NG_TRIGGER_CLASSNAME); 9177 addClass(element, NG_TRIGGER_CLASSNAME + '-' + triggerName); 9178 9179 this._engine.statesByElement.set(element, triggersWithStates = new Map()); 9180 } 9181 9182 let fromState = triggersWithStates.get(triggerName); 9183 const toState = new StateValue(value, this.id); 9184 const isObj = value && value.hasOwnProperty('value'); 9185 9186 if (!isObj && fromState) { 9187 toState.absorbOptions(fromState.options); 9188 } 9189 9190 triggersWithStates.set(triggerName, toState); 9191 9192 if (!fromState) { 9193 fromState = DEFAULT_STATE_VALUE; 9194 } 9195 9196 const isRemoval = toState.value === VOID_VALUE; // normally this isn't reached by here, however, if an object expression 9197 // is passed in then it may be a new object each time. Comparing the value 9198 // is important since that will stay the same despite there being a new object. 9199 // The removal arc here is special cased because the same element is triggered 9200 // twice in the event that it contains animations on the outer/inner portions 9201 // of the host container 9202 9203 if (!isRemoval && fromState.value === toState.value) { 9204 // this means that despite the value not changing, some inner params 9205 // have changed which means that the animation final styles need to be applied 9206 if (!objEquals(fromState.params, toState.params)) { 9207 const errors = []; 9208 const fromStyles = trigger.matchStyles(fromState.value, fromState.params, errors); 9209 const toStyles = trigger.matchStyles(toState.value, toState.params, errors); 9210 9211 if (errors.length) { 9212 this._engine.reportError(errors); 9213 } else { 9214 this._engine.afterFlush(() => { 9215 eraseStyles(element, fromStyles); 9216 setStyles(element, toStyles); 9217 }); 9218 } 9219 } 9220 9221 return; 9222 } 9223 9224 const playersOnElement = getOrSetDefaultValue(this._engine.playersByElement, element, []); 9225 playersOnElement.forEach(player => { 9226 // only remove the player if it is queued on the EXACT same trigger/namespace 9227 // we only also deal with queued players here because if the animation has 9228 // started then we want to keep the player alive until the flush happens 9229 // (which is where the previousPlayers are passed into the new player) 9230 if (player.namespaceId == this.id && player.triggerName == triggerName && player.queued) { 9231 player.destroy(); 9232 } 9233 }); 9234 let transition = trigger.matchTransition(fromState.value, toState.value, element, toState.params); 9235 let isFallbackTransition = false; 9236 9237 if (!transition) { 9238 if (!defaultToFallback) return; 9239 transition = trigger.fallbackTransition; 9240 isFallbackTransition = true; 9241 } 9242 9243 this._engine.totalQueuedPlayers++; 9244 9245 this._queue.push({ 9246 element, 9247 triggerName, 9248 transition, 9249 fromState, 9250 toState, 9251 player, 9252 isFallbackTransition 9253 }); 9254 9255 if (!isFallbackTransition) { 9256 addClass(element, QUEUED_CLASSNAME); 9257 player.onStart(() => { 9258 removeClass(element, QUEUED_CLASSNAME); 9259 }); 9260 } 9261 9262 player.onDone(() => { 9263 let index = this.players.indexOf(player); 9264 9265 if (index >= 0) { 9266 this.players.splice(index, 1); 9267 } 9268 9269 const players = this._engine.playersByElement.get(element); 9270 9271 if (players) { 9272 let index = players.indexOf(player); 9273 9274 if (index >= 0) { 9275 players.splice(index, 1); 9276 } 9277 } 9278 }); 9279 this.players.push(player); 9280 playersOnElement.push(player); 9281 return player; 9282 } 9283 9284 deregister(name) { 9285 this._triggers.delete(name); 9286 9287 this._engine.statesByElement.forEach(stateMap => stateMap.delete(name)); 9288 9289 this._elementListeners.forEach((listeners, element) => { 9290 this._elementListeners.set(element, listeners.filter(entry => { 9291 return entry.name != name; 9292 })); 9293 }); 9294 } 9295 9296 clearElementCache(element) { 9297 this._engine.statesByElement.delete(element); 9298 9299 this._elementListeners.delete(element); 9300 9301 const elementPlayers = this._engine.playersByElement.get(element); 9302 9303 if (elementPlayers) { 9304 elementPlayers.forEach(player => player.destroy()); 9305 9306 this._engine.playersByElement.delete(element); 9307 } 9308 } 9309 9310 _signalRemovalForInnerTriggers(rootElement, context) { 9311 const elements = this._engine.driver.query(rootElement, NG_TRIGGER_SELECTOR, true); // emulate a leave animation for all inner nodes within this node. 9312 // If there are no animations found for any of the nodes then clear the cache 9313 // for the element. 9314 9315 9316 elements.forEach(elm => { 9317 // this means that an inner remove() operation has already kicked off 9318 // the animation on this element... 9319 if (elm[REMOVAL_FLAG]) return; 9320 9321 const namespaces = this._engine.fetchNamespacesByElement(elm); 9322 9323 if (namespaces.size) { 9324 namespaces.forEach(ns => ns.triggerLeaveAnimation(elm, context, false, true)); 9325 } else { 9326 this.clearElementCache(elm); 9327 } 9328 }); // If the child elements were removed along with the parent, their animations might not 9329 // have completed. Clear all the elements from the cache so we don't end up with a memory leak. 9330 9331 this._engine.afterFlushAnimationsDone(() => elements.forEach(elm => this.clearElementCache(elm))); 9332 } 9333 9334 triggerLeaveAnimation(element, context, destroyAfterComplete, defaultToFallback) { 9335 const triggerStates = this._engine.statesByElement.get(element); 9336 9337 const previousTriggersValues = new Map(); 9338 9339 if (triggerStates) { 9340 const players = []; 9341 triggerStates.forEach((state, triggerName) => { 9342 previousTriggersValues.set(triggerName, state.value); // this check is here in the event that an element is removed 9343 // twice (both on the host level and the component level) 9344 9345 if (this._triggers.has(triggerName)) { 9346 const player = this.trigger(element, triggerName, VOID_VALUE, defaultToFallback); 9347 9348 if (player) { 9349 players.push(player); 9350 } 9351 } 9352 }); 9353 9354 if (players.length) { 9355 this._engine.markElementAsRemoved(this.id, element, true, context, previousTriggersValues); 9356 9357 if (destroyAfterComplete) { 9358 optimizeGroupPlayer(players).onDone(() => this._engine.processLeaveNode(element)); 9359 } 9360 9361 return true; 9362 } 9363 } 9364 9365 return false; 9366 } 9367 9368 prepareLeaveAnimationListeners(element) { 9369 const listeners = this._elementListeners.get(element); 9370 9371 const elementStates = this._engine.statesByElement.get(element); // if this statement fails then it means that the element was picked up 9372 // by an earlier flush (or there are no listeners at all to track the leave). 9373 9374 9375 if (listeners && elementStates) { 9376 const visitedTriggers = new Set(); 9377 listeners.forEach(listener => { 9378 const triggerName = listener.name; 9379 if (visitedTriggers.has(triggerName)) return; 9380 visitedTriggers.add(triggerName); 9381 9382 const trigger = this._triggers.get(triggerName); 9383 9384 const transition = trigger.fallbackTransition; 9385 const fromState = elementStates.get(triggerName) || DEFAULT_STATE_VALUE; 9386 const toState = new StateValue(VOID_VALUE); 9387 const player = new TransitionAnimationPlayer(this.id, triggerName, element); 9388 this._engine.totalQueuedPlayers++; 9389 9390 this._queue.push({ 9391 element, 9392 triggerName, 9393 transition, 9394 fromState, 9395 toState, 9396 player, 9397 isFallbackTransition: true 9398 }); 9399 }); 9400 } 9401 } 9402 9403 removeNode(element, context) { 9404 const engine = this._engine; 9405 9406 if (element.childElementCount) { 9407 this._signalRemovalForInnerTriggers(element, context); 9408 } // this means that a * => VOID animation was detected and kicked off 9409 9410 9411 if (this.triggerLeaveAnimation(element, context, true)) return; // find the player that is animating and make sure that the 9412 // removal is delayed until that player has completed 9413 9414 let containsPotentialParentTransition = false; 9415 9416 if (engine.totalAnimations) { 9417 const currentPlayers = engine.players.length ? engine.playersByQueriedElement.get(element) : []; // when this `if statement` does not continue forward it means that 9418 // a previous animation query has selected the current element and 9419 // is animating it. In this situation want to continue forwards and 9420 // allow the element to be queued up for animation later. 9421 9422 if (currentPlayers && currentPlayers.length) { 9423 containsPotentialParentTransition = true; 9424 } else { 9425 let parent = element; 9426 9427 while (parent = parent.parentNode) { 9428 const triggers = engine.statesByElement.get(parent); 9429 9430 if (triggers) { 9431 containsPotentialParentTransition = true; 9432 break; 9433 } 9434 } 9435 } 9436 } // at this stage we know that the element will either get removed 9437 // during flush or will be picked up by a parent query. Either way 9438 // we need to fire the listeners for this element when it DOES get 9439 // removed (once the query parent animation is done or after flush) 9440 9441 9442 this.prepareLeaveAnimationListeners(element); // whether or not a parent has an animation we need to delay the deferral of the leave 9443 // operation until we have more information (which we do after flush() has been called) 9444 9445 if (containsPotentialParentTransition) { 9446 engine.markElementAsRemoved(this.id, element, false, context); 9447 } else { 9448 const removalFlag = element[REMOVAL_FLAG]; 9449 9450 if (!removalFlag || removalFlag === NULL_REMOVAL_STATE) { 9451 // we do this after the flush has occurred such 9452 // that the callbacks can be fired 9453 engine.afterFlush(() => this.clearElementCache(element)); 9454 engine.destroyInnerAnimations(element); 9455 9456 engine._onRemovalComplete(element, context); 9457 } 9458 } 9459 } 9460 9461 insertNode(element, parent) { 9462 addClass(element, this._hostClassName); 9463 } 9464 9465 drainQueuedTransitions(microtaskId) { 9466 const instructions = []; 9467 9468 this._queue.forEach(entry => { 9469 const player = entry.player; 9470 if (player.destroyed) return; 9471 const element = entry.element; 9472 9473 const listeners = this._elementListeners.get(element); 9474 9475 if (listeners) { 9476 listeners.forEach(listener => { 9477 if (listener.name == entry.triggerName) { 9478 const baseEvent = makeAnimationEvent(element, entry.triggerName, entry.fromState.value, entry.toState.value); 9479 baseEvent['_data'] = microtaskId; 9480 listenOnPlayer(entry.player, listener.phase, baseEvent, listener.callback); 9481 } 9482 }); 9483 } 9484 9485 if (player.markedForDestroy) { 9486 this._engine.afterFlush(() => { 9487 // now we can destroy the element properly since the event listeners have 9488 // been bound to the player 9489 player.destroy(); 9490 }); 9491 } else { 9492 instructions.push(entry); 9493 } 9494 }); 9495 9496 this._queue = []; 9497 return instructions.sort((a, b) => { 9498 // if depCount == 0 them move to front 9499 // otherwise if a contains b then move back 9500 const d0 = a.transition.ast.depCount; 9501 const d1 = b.transition.ast.depCount; 9502 9503 if (d0 == 0 || d1 == 0) { 9504 return d0 - d1; 9505 } 9506 9507 return this._engine.driver.containsElement(a.element, b.element) ? 1 : -1; 9508 }); 9509 } 9510 9511 destroy(context) {
9512 this.players.forEach(p => p.destroy()); 9513 9514 this._signalRemovalForInnerTriggers(this.hostElement, context); 9515 } 9516 9517 elementContainsData(element) { 9518 let containsData = false; 9519 if (this._elementListeners.has(element)) containsData = true; 9520 containsData = (this._queue.find(entry => entry.element === element) ? true : false) || containsData; 9521 return containsData; 9522 } 9523 9524} 9525 9526class TransitionAnimationEngine { 9527 constructor(bodyNode, driver, _normalizer) { 9528 this.bodyNode = bodyNode; 9529 this.driver = driver; 9530 this._normalizer = _normalizer; 9531 this.players = []; 9532 this.newHostElements = new Map(); 9533 this.playersByElement = new Map(); 9534 this.playersByQueriedElement = new Map(); 9535 this.statesByElement = new Map(); 9536 this.disabledNodes = new Set(); 9537 this.totalAnimations = 0; 9538 this.totalQueuedPlayers = 0; 9539 this._namespaceLookup = {}; 9540 this._namespaceList = []; 9541 this._flushFns = []; 9542 this._whenQuietFns = []; 9543 this.namespacesByHostElement = new Map(); 9544 this.collectedEnterElements = []; 9545 this.collectedLeaveElements = []; // this method is designed to be overridden by the code that uses this engine 9546 9547 this.onRemovalComplete = (element, context) => {}; 9548 } 9549 /** @internal */ 9550 9551 9552 _onRemovalComplete(element, context) { 9553 this.onRemovalComplete(element, context); 9554 } 9555 9556 get queuedPlayers() { 9557 const players = []; 9558 9559 this._namespaceList.forEach(ns => { 9560 ns.players.forEach(player => { 9561 if (player.queued) { 9562 players.push(player); 9563 } 9564 }); 9565 }); 9566 9567 return players; 9568 } 9569 9570 createNamespace(namespaceId, hostElement) { 9571 const ns = new AnimationTransitionNamespace(namespaceId, hostElement, this); 9572 9573 if (this.bodyNode && this.driver.containsElement(this.bodyNode, hostElement)) { 9574 this._balanceNamespaceList(ns, hostElement); 9575 } else { 9576 // defer this later until flush during when the host element has 9577 // been inserted so that we know exactly where to place it in 9578 // the namespace list 9579 this.newHostElements.set(hostElement, ns); // given that this host element is a part of the animation code, it 9580 // may or may not be inserted by a parent node that is of an 9581 // animation renderer type. If this happens then we can still have 9582 // access to this item when we query for :enter nodes. If the parent 9583 // is a renderer then the set data-structure will normalize the entry 9584 9585 this.collectEnterElement(hostElement); 9586 } 9587 9588 return this._namespaceLookup[namespaceId] = ns; 9589 } 9590 9591 _balanceNamespaceList(ns, hostElement) { 9592 const namespaceList = this._namespaceList; 9593 const namespacesByHostElement = this.namespacesByHostElement; 9594 const limit = namespaceList.length - 1; 9595 9596 if (limit >= 0) { 9597 let found = false; // Find the closest ancestor with an existing namespace so we can then insert `ns` after it, 9598 // establishing a top-down ordering of namespaces in `this._namespaceList`. 9599 9600 let ancestor = this.driver.getParentElement(hostElement); 9601 9602 while (ancestor) { 9603 const ancestorNs = namespacesByHostElement.get(ancestor); 9604 9605 if (ancestorNs) { 9606 // An animation namespace has been registered for this ancestor, so we insert `ns` 9607 // right after it to establish top-down ordering of animation namespaces. 9608 const index = namespaceList.indexOf(ancestorNs); 9609 namespaceList.splice(index + 1, 0, ns); 9610 found = true; 9611 break; 9612 } 9613 9614 ancestor = this.driver.getParentElement(ancestor); 9615 } 9616 9617 if (!found) { 9618 // No namespace exists that is an ancestor of `ns`, so `ns` is inserted at the front to 9619 // ensure that any existing descendants are ordered after `ns`, retaining the desired 9620 // top-down ordering. 9621 namespaceList.unshift(ns); 9622 } 9623 } else { 9624 namespaceList.push(ns); 9625 } 9626 9627 namespacesByHostElement.set(hostElement, ns); 9628 return ns; 9629 } 9630 9631 register(namespaceId, hostElement) { 9632 let ns = this._namespaceLookup[namespaceId]; 9633 9634 if (!ns) { 9635 ns = this.createNamespace(namespaceId, hostElement); 9636 } 9637 9638 return ns; 9639 } 9640 9641 registerTrigger(namespaceId, name, trigger) { 9642 let ns = this._namespaceLookup[namespaceId]; 9643 9644 if (ns && ns.register(name, trigger)) { 9645 this.totalAnimations++; 9646 } 9647 } 9648 9649 destroy(namespaceId, context) { 9650 if (!namespaceId) return; 9651 9652 const ns = this._fetchNamespace(namespaceId); 9653 9654 this.afterFlush(() => { 9655 this.namespacesByHostElement.delete(ns.hostElement); 9656 delete this._namespaceLookup[namespaceId]; 9657 9658 const index = this._namespaceList.indexOf(ns); 9659 9660 if (index >= 0) { 9661 this._namespaceList.splice(index, 1); 9662 } 9663 }); 9664 this.afterFlushAnimationsDone(() => ns.destroy(context)); 9665 } 9666 9667 _fetchNamespace(id) { 9668 return this._namespaceLookup[id]; 9669 } 9670 9671 fetchNamespacesByElement(element) { 9672 // normally there should only be one namespace per element, however 9673 // if @triggers are placed on both the component element and then 9674 // its host element (within the component code) then there will be 9675 // two namespaces returned. We use a set here to simply deduplicate 9676 // the namespaces in case (for the reason described above) there are multiple triggers 9677 const namespaces = new Set(); 9678 const elementStates = this.statesByElement.get(element); 9679 9680 if (elementStates) { 9681 for (let stateValue of elementStates.values()) { 9682 if (stateValue.namespaceId) { 9683 const ns = this._fetchNamespace(stateValue.namespaceId); 9684 9685 if (ns) { 9686 namespaces.add(ns); 9687 } 9688 } 9689 } 9690 } 9691 9692 return namespaces; 9693 } 9694 9695 trigger(namespaceId, element, name, value) { 9696 if (isElementNode(element)) { 9697 const ns = this._fetchNamespace(namespaceId); 9698 9699 if (ns) { 9700 ns.trigger(element, name, value); 9701 return true; 9702 } 9703 } 9704 9705 return false;
vendor: 8,359 bytes, lines 9706-9965
9706 } 9707 9708 insertNode(namespaceId, element, parent, insertBefore) { 9709 if (!isElementNode(element)) return; // special case for when an element is removed and reinserted (move operation) 9710 // when this occurs we do not want to use the element for deletion later 9711 9712 const details = element[REMOVAL_FLAG]; 9713 9714 if (details && details.setForRemoval) { 9715 details.setForRemoval = false; 9716 details.setForMove = true; 9717 const index = this.collectedLeaveElements.indexOf(element); 9718 9719 if (index >= 0) { 9720 this.collectedLeaveElements.splice(index, 1); 9721 } 9722 } // in the event that the namespaceId is blank then the caller 9723 // code does not contain any animation code in it, but it is 9724 // just being called so that the node is marked as being inserted 9725 9726 9727 if (namespaceId) { 9728 const ns = this._fetchNamespace(namespaceId); // This if-statement is a workaround for router issue #21947. 9729 // The router sometimes hits a race condition where while a route 9730 // is being instantiated a new navigation arrives, triggering leave 9731 // animation of DOM that has not been fully initialized, until this 9732 // is resolved, we need to handle the scenario when DOM is not in a 9733 // consistent state during the animation. 9734 9735 9736 if (ns) { 9737 ns.insertNode(element, parent); 9738 } 9739 } // only *directives and host elements are inserted before 9740 9741 9742 if (insertBefore) { 9743 this.collectEnterElement(element); 9744 } 9745 } 9746 9747 collectEnterElement(element) { 9748 this.collectedEnterElements.push(element); 9749 } 9750 9751 markElementAsDisabled(element, value) { 9752 if (value) { 9753 if (!this.disabledNodes.has(element)) { 9754 this.disabledNodes.add(element); 9755 addClass(element, DISABLED_CLASSNAME); 9756 } 9757 } else if (this.disabledNodes.has(element)) { 9758 this.disabledNodes.delete(element); 9759 removeClass(element, DISABLED_CLASSNAME); 9760 } 9761 } 9762 9763 removeNode(namespaceId, element, isHostElement, context) { 9764 if (isElementNode(element)) { 9765 const ns = namespaceId ? this._fetchNamespace(namespaceId) : null; 9766 9767 if (ns) { 9768 ns.removeNode(element, context); 9769 } else { 9770 this.markElementAsRemoved(namespaceId, element, false, context); 9771 } 9772 9773 if (isHostElement) { 9774 const hostNS = this.namespacesByHostElement.get(element); 9775 9776 if (hostNS && hostNS.id !== namespaceId) { 9777 hostNS.removeNode(element, context); 9778 } 9779 } 9780 } else { 9781 this._onRemovalComplete(element, context); 9782 } 9783 } 9784 9785 markElementAsRemoved(namespaceId, element, hasAnimation, context, previousTriggersValues) { 9786 this.collectedLeaveElements.push(element); 9787 element[REMOVAL_FLAG] = { 9788 namespaceId, 9789 setForRemoval: context, 9790 hasAnimation, 9791 removedBeforeQueried: false, 9792 previousTriggersValues 9793 }; 9794 } 9795 9796 listen(namespaceId, element, name, phase, callback) { 9797 if (isElementNode(element)) { 9798 return this._fetchNamespace(namespaceId).listen(element, name, phase, callback); 9799 } 9800 9801 return () => {}; 9802 } 9803 9804 _buildInstruction(entry, subTimelines, enterClassName, leaveClassName, skipBuildAst) { 9805 return entry.transition.build(this.driver, entry.element, entry.fromState.value, entry.toState.value, enterClassName, leaveClassName, entry.fromState.options, entry.toState.options, subTimelines, skipBuildAst); 9806 } 9807 9808 destroyInnerAnimations(containerElement) { 9809 let elements = this.driver.query(containerElement, NG_TRIGGER_SELECTOR, true); 9810 elements.forEach(element => this.destroyActiveAnimationsForElement(element)); 9811 if (this.playersByQueriedElement.size == 0) return; 9812 elements = this.driver.query(containerElement, NG_ANIMATING_SELECTOR, true); 9813 elements.forEach(element => this.finishActiveQueriedAnimationOnElement(element)); 9814 } 9815 9816 destroyActiveAnimationsForElement(element) { 9817 const players = this.playersByElement.get(element); 9818 9819 if (players) { 9820 players.forEach(player => { 9821 // special case for when an element is set for destruction, but hasn't started. 9822 // in this situation we want to delay the destruction until the flush occurs 9823 // so that any event listeners attached to the player are triggered. 9824 if (player.queued) { 9825 player.markedForDestroy = true; 9826 } else { 9827 player.destroy(); 9828 } 9829 }); 9830 } 9831 } 9832 9833 finishActiveQueriedAnimationOnElement(element) { 9834 const players = this.playersByQueriedElement.get(element); 9835 9836 if (players) { 9837 players.forEach(player => player.finish()); 9838 } 9839 } 9840 9841 whenRenderingDone() { 9842 return new Promise(resolve => { 9843 if (this.players.length) { 9844 return optimizeGroupPlayer(this.players).onDone(() => resolve()); 9845 } else { 9846 resolve(); 9847 } 9848 }); 9849 } 9850 9851 processLeaveNode(element) { 9852 const details = element[REMOVAL_FLAG]; 9853 9854 if (details && details.setForRemoval) { 9855 // this will prevent it from removing it twice 9856 element[REMOVAL_FLAG] = NULL_REMOVAL_STATE; 9857 9858 if (details.namespaceId) { 9859 this.destroyInnerAnimations(element); 9860 9861 const ns = this._fetchNamespace(details.namespaceId); 9862 9863 if (ns) { 9864 ns.clearElementCache(element); 9865 } 9866 } 9867 9868 this._onRemovalComplete(element, details.setForRemoval); 9869 } 9870 9871 if (element.classList?.contains(DISABLED_CLASSNAME)) { 9872 this.markElementAsDisabled(element, false); 9873 } 9874 9875 this.driver.query(element, DISABLED_SELECTOR, true).forEach(node => { 9876 this.markElementAsDisabled(node, false); 9877 }); 9878 } 9879 9880 flush(microtaskId = -1) { 9881 let players = []; 9882 9883 if (this.newHostElements.size) { 9884 this.newHostElements.forEach((ns, element) => this._balanceNamespaceList(ns, element)); 9885 this.newHostElements.clear(); 9886 } 9887 9888 if (this.totalAnimations && this.collectedEnterElements.length) { 9889 for (let i = 0; i < this.collectedEnterElements.length; i++) { 9890 const elm = this.collectedEnterElements[i]; 9891 addClass(elm, STAR_CLASSNAME); 9892 } 9893 } 9894 9895 if (this._namespaceList.length && (this.totalQueuedPlayers || this.collectedLeaveElements.length)) { 9896 const cleanupFns = []; 9897 9898 try { 9899 players = this._flushAnimations(cleanupFns, microtaskId); 9900 } finally { 9901 for (let i = 0; i < cleanupFns.length; i++) { 9902 cleanupFns[i](); 9903 } 9904 } 9905 } else { 9906 for (let i = 0; i < this.collectedLeaveElements.length; i++) { 9907 const element = this.collectedLeaveElements[i]; 9908 this.processLeaveNode(element); 9909 } 9910 } 9911 9912 this.totalQueuedPlayers = 0; 9913 this.collectedEnterElements.length = 0; 9914 this.collectedLeaveElements.length = 0; 9915 9916 this._flushFns.forEach(fn => fn()); 9917 9918 this._flushFns = []; 9919 9920 if (this._whenQuietFns.length) { 9921 // we move these over to a variable so that 9922 // if any new callbacks are registered in another 9923 // flush they do not populate the existing set 9924 const quietFns = this._whenQuietFns; 9925 this._whenQuietFns = []; 9926 9927 if (players.length) { 9928 optimizeGroupPlayer(players).onDone(() => { 9929 quietFns.forEach(fn => fn()); 9930 }); 9931 } else { 9932 quietFns.forEach(fn => fn()); 9933 } 9934 } 9935 } 9936 9937 reportError(errors) { 9938 throw triggerTransitionsFailed(errors); 9939 } 9940 9941 _flushAnimations(cleanupFns, microtaskId) { 9942 const subTimelines = new ElementInstructionMap(); 9943 const skippedPlayers = []; 9944 const skippedPlayersMap = new Map(); 9945 const queuedInstructions = []; 9946 const queriedElements = new Map(); 9947 const allPreStyleElements = new Map(); 9948 const allPostStyleElements = new Map(); 9949 const disabledElementsSet = new Set(); 9950 this.disabledNodes.forEach(node => { 9951 disabledElementsSet.add(node); 9952 const nodesThatAreDisabled = this.driver.query(node, QUEUED_SELECTOR, true); 9953 9954 for (let i = 0; i < nodesThatAreDisabled.length; i++) { 9955 disabledElementsSet.add(nodesThatAreDisabled[i]); 9956 } 9957 }); 9958 const bodyNode = this.bodyNode; 9959 const allTriggerElements = Array.from(this.statesByElement.keys()); 9960 const enterNodeMap = buildRootMap(allTriggerElements, this.collectedEnterElements); // this must occur before the instructions are built below such that 9961 // the :enter queries match the elements (since the timeline queries 9962 // are fired during instruction building). 9963 9964 const enterNodeMapIds = new Map(); 9965 let i = 0;
9966 enterNodeMap.forEach((nodes, root) => { 9967 const className = ENTER_CLASSNAME + i++; 9968 enterNodeMapIds.set(root, className); 9969 nodes.forEach(node => addClass(node, className)); 9970 }); 9971 const allLeaveNodes = []; 9972 const mergedLeaveNodes = new Set(); 9973 const leaveNodesWithoutAnimations = new Set(); 9974 9975 for (let i = 0; i < this.collectedLeaveElements.length; i++) { 9976 const element = this.collectedLeaveElements[i]; 9977 const details = element[REMOVAL_FLAG]; 9978 9979 if (details && details.setForRemoval) { 9980 allLeaveNodes.push(element); 9981 mergedLeaveNodes.add(element); 9982 9983 if (details.hasAnimation) { 9984 this.driver.query(element, STAR_SELECTOR, true).forEach(elm => mergedLeaveNodes.add(elm)); 9985 } else { 9986 leaveNodesWithoutAnimations.add(element); 9987 } 9988 } 9989 } 9990 9991 const leaveNodeMapIds = new Map(); 9992 const leaveNodeMap = buildRootMap(allTriggerElements, Array.from(mergedLeaveNodes)); 9993 leaveNodeMap.forEach((nodes, root) => { 9994 const className = LEAVE_CLASSNAME + i++; 9995 leaveNodeMapIds.set(root, className); 9996 nodes.forEach(node => addClass(node, className)); 9997 }); 9998 cleanupFns.push(() => {
vendor: 4,150 bytes, lines 9999-10096
9999 enterNodeMap.forEach((nodes, root) => { 10000 const className = enterNodeMapIds.get(root); 10001 nodes.forEach(node => removeClass(node, className)); 10002 }); 10003 leaveNodeMap.forEach((nodes, root) => { 10004 const className = leaveNodeMapIds.get(root); 10005 nodes.forEach(node => removeClass(node, className)); 10006 }); 10007 allLeaveNodes.forEach(element => { 10008 this.processLeaveNode(element); 10009 }); 10010 }); 10011 const allPlayers = []; 10012 const erroneousTransitions = []; 10013 10014 for (let i = this._namespaceList.length - 1; i >= 0; i--) { 10015 const ns = this._namespaceList[i]; 10016 ns.drainQueuedTransitions(microtaskId).forEach(entry => { 10017 const player = entry.player; 10018 const element = entry.element; 10019 allPlayers.push(player); 10020 10021 if (this.collectedEnterElements.length) { 10022 const details = element[REMOVAL_FLAG]; // animations for move operations (elements being removed and reinserted, 10023 // e.g. when the order of an *ngFor list changes) are currently not supported 10024 10025 if (details && details.setForMove) { 10026 if (details.previousTriggersValues && details.previousTriggersValues.has(entry.triggerName)) { 10027 const previousValue = details.previousTriggersValues.get(entry.triggerName); // we need to restore the previous trigger value since the element has 10028 // only been moved and hasn't actually left the DOM 10029 10030 const triggersWithStates = this.statesByElement.get(entry.element); 10031 10032 if (triggersWithStates && triggersWithStates.has(entry.triggerName)) { 10033 const state = triggersWithStates.get(entry.triggerName); 10034 state.value = previousValue; 10035 triggersWithStates.set(entry.triggerName, state); 10036 } 10037 } 10038 10039 player.destroy(); 10040 return; 10041 } 10042 } 10043 10044 const nodeIsOrphaned = !bodyNode || !this.driver.containsElement(bodyNode, element); 10045 const leaveClassName = leaveNodeMapIds.get(element); 10046 const enterClassName = enterNodeMapIds.get(element); 10047 10048 const instruction = this._buildInstruction(entry, subTimelines, enterClassName, leaveClassName, nodeIsOrphaned); 10049 10050 if (instruction.errors && instruction.errors.length) { 10051 erroneousTransitions.push(instruction); 10052 return; 10053 } // even though the element may not be in the DOM, it may still 10054 // be added at a later point (due to the mechanics of content 10055 // projection and/or dynamic component insertion) therefore it's 10056 // important to still style the element. 10057 10058 10059 if (nodeIsOrphaned) { 10060 player.onStart(() => eraseStyles(element, instruction.fromStyles)); 10061 player.onDestroy(() => setStyles(element, instruction.toStyles)); 10062 skippedPlayers.push(player); 10063 return; 10064 } // if an unmatched transition is queued and ready to go 10065 // then it SHOULD NOT render an animation and cancel the 10066 // previously running animations. 10067 10068 10069 if (entry.isFallbackTransition) { 10070 player.onStart(() => eraseStyles(element, instruction.fromStyles)); 10071 player.onDestroy(() => setStyles(element, instruction.toStyles)); 10072 skippedPlayers.push(player); 10073 return; 10074 } // this means that if a parent animation uses this animation as a sub-trigger 10075 // then it will instruct the timeline builder not to add a player delay, but 10076 // instead stretch the first keyframe gap until the animation starts. This is 10077 // important in order to prevent extra initialization styles from being 10078 // required by the user for the animation. 10079 10080 10081 const timelines = []; 10082 instruction.timelines.forEach(tl => { 10083 tl.stretchStartingKeyframe = true; 10084 10085 if (!this.disabledNodes.has(tl.element)) { 10086 timelines.push(tl); 10087 } 10088 }); 10089 instruction.timelines = timelines; 10090 subTimelines.append(element, instruction.timelines); 10091 const tuple = { 10092 instruction, 10093 player, 10094 element 10095 }; 10096 queuedInstructions.push(tuple);
10097 instruction.queriedElements.forEach(element => getOrSetDefaultValue(queriedElements, element, []).push(player)); 10098 instruction.preStyleProps.forEach((stringMap, element) => { 10099 if (stringMap.size) { 10100 let setVal = allPreStyleElements.get(element); 10101 10102 if (!setVal) { 10103 allPreStyleElements.set(element, setVal = new Set()); 10104 } 10105 10106 stringMap.forEach((_, prop) => setVal.add(prop)); 10107 } 10108 }); 10109 instruction.postStyleProps.forEach((stringMap, element) => { 10110 let setVal = allPostStyleElements.get(element); 10111 10112 if (!setVal) { 10113 allPostStyleElements.set(element, setVal = new Set()); 10114 } 10115 10116 stringMap.forEach((_, prop) => setVal.add(prop)); 10117 }); 10118 }); 10119 } 10120 10121 if (erroneousTransitions.length) { 10122 const errors = []; 10123 erroneousTransitions.forEach(instruction => { 10124 errors.push(transitionFailed(instruction.triggerName, instruction.errors)); 10125 }); 10126 allPlayers.forEach(player => player.destroy()); 10127 this.reportError(errors); 10128 } 10129 10130 const allPreviousPlayersMap = new Map(); // this map tells us which element in the DOM tree is contained by 10131 // which animation. Further down this map will get populated once 10132 // the players are built and in doing so we can use it to efficiently 10133 // figure out if a sub player is skipped due to a parent player having priority. 10134 10135 const animationElementMap = new Map(); 10136 queuedInstructions.forEach(entry => { 10137 const element = entry.element; 10138 10139 if (subTimelines.has(element)) { 10140 animationElementMap.set(element, element); 10141 10142 this._beforeAnimationBuild(entry.player.namespaceId, entry.instruction, allPreviousPlayersMap); 10143 } 10144 }); 10145 skippedPlayers.forEach(player => { 10146 const element = player.element; 10147 10148 const previousPlayers = this._getPreviousPlayers(element, false, player.namespaceId, player.triggerName, null); 10149 10150 previousPlayers.forEach(prevPlayer => { 10151 getOrSetDefaultValue(allPreviousPlayersMap, element, []).push(prevPlayer); 10152 prevPlayer.destroy(); 10153 }); 10154 }); // this is a special case for nodes that will be removed either by 10155 // having their own leave animations or by being queried in a container 10156 // that will be removed once a parent animation is complete. The idea 10157 // here is that * styles must be identical to ! styles because of 10158 // backwards compatibility (* is also filled in by default in many places). 10159 // Otherwise * styles will return an empty value or "auto" since the element 10160 // passed to getComputedStyle will not be visible (since * === destination) 10161 10162 const replaceNodes = allLeaveNodes.filter(node => { 10163 return replacePostStylesAsPre(node, allPreStyleElements, allPostStyleElements); 10164 }); // POST STAGE: fill the * styles 10165 10166 const postStylesMap = new Map(); 10167 const allLeaveQueriedNodes = cloakAndComputeStyles(postStylesMap, this.driver, leaveNodesWithoutAnimations, allPostStyleElements, _angular_animations__WEBPACK_IMPORTED_MODULE_1__.AUTO_STYLE); 10168 allLeaveQueriedNodes.forEach(node => { 10169 if (replacePostStylesAsPre(node, allPreStyleElements, allPostStyleElements)) { 10170 replaceNodes.push(node); 10171 } 10172 }); // PRE STAGE: fill the ! styles 10173 10174 const preStylesMap = new Map();
vendor: 5,685 bytes, lines 10175-10314
10175 enterNodeMap.forEach((nodes, root) => { 10176 cloakAndComputeStyles(preStylesMap, this.driver, new Set(nodes), allPreStyleElements, _angular_animations__WEBPACK_IMPORTED_MODULE_1__["ɵPRE_STYLE"]); 10177 }); 10178 replaceNodes.forEach(node => { 10179 const post = postStylesMap.get(node); 10180 const pre = preStylesMap.get(node); 10181 postStylesMap.set(node, new Map([...Array.from(post?.entries() ?? []), ...Array.from(pre?.entries() ?? [])])); 10182 }); 10183 const rootPlayers = []; 10184 const subPlayers = []; 10185 const NO_PARENT_ANIMATION_ELEMENT_DETECTED = {}; 10186 queuedInstructions.forEach(entry => { 10187 const { 10188 element, 10189 player, 10190 instruction 10191 } = entry; // this means that it was never consumed by a parent animation which 10192 // means that it is independent and therefore should be set for animation 10193 10194 if (subTimelines.has(element)) { 10195 if (disabledElementsSet.has(element)) { 10196 player.onDestroy(() => setStyles(element, instruction.toStyles)); 10197 player.disabled = true; 10198 player.overrideTotalTime(instruction.totalTime); 10199 skippedPlayers.push(player); 10200 return; 10201 } // this will flow up the DOM and query the map to figure out 10202 // if a parent animation has priority over it. In the situation 10203 // that a parent is detected then it will cancel the loop. If 10204 // nothing is detected, or it takes a few hops to find a parent, 10205 // then it will fill in the missing nodes and signal them as having 10206 // a detected parent (or a NO_PARENT value via a special constant). 10207 10208 10209 let parentWithAnimation = NO_PARENT_ANIMATION_ELEMENT_DETECTED; 10210 10211 if (animationElementMap.size > 1) { 10212 let elm = element; 10213 const parentsToAdd = []; 10214 10215 while (elm = elm.parentNode) { 10216 const detectedParent = animationElementMap.get(elm); 10217 10218 if (detectedParent) { 10219 parentWithAnimation = detectedParent; 10220 break; 10221 } 10222 10223 parentsToAdd.push(elm); 10224 } 10225 10226 parentsToAdd.forEach(parent => animationElementMap.set(parent, parentWithAnimation)); 10227 } 10228 10229 const innerPlayer = this._buildAnimation(player.namespaceId, instruction, allPreviousPlayersMap, skippedPlayersMap, preStylesMap, postStylesMap); 10230 10231 player.setRealPlayer(innerPlayer); 10232 10233 if (parentWithAnimation === NO_PARENT_ANIMATION_ELEMENT_DETECTED) { 10234 rootPlayers.push(player); 10235 } else { 10236 const parentPlayers = this.playersByElement.get(parentWithAnimation); 10237 10238 if (parentPlayers && parentPlayers.length) { 10239 player.parentPlayer = optimizeGroupPlayer(parentPlayers); 10240 } 10241 10242 skippedPlayers.push(player); 10243 } 10244 } else { 10245 eraseStyles(element, instruction.fromStyles); 10246 player.onDestroy(() => setStyles(element, instruction.toStyles)); // there still might be a ancestor player animating this 10247 // element therefore we will still add it as a sub player 10248 // even if its animation may be disabled 10249 10250 subPlayers.push(player); 10251 10252 if (disabledElementsSet.has(element)) { 10253 skippedPlayers.push(player); 10254 } 10255 } 10256 }); // find all of the sub players' corresponding inner animation players 10257 10258 subPlayers.forEach(player => { 10259 // even if no players are found for a sub animation it 10260 // will still complete itself after the next tick since it's Noop 10261 const playersForElement = skippedPlayersMap.get(player.element); 10262 10263 if (playersForElement && playersForElement.length) { 10264 const innerPlayer = optimizeGroupPlayer(playersForElement); 10265 player.setRealPlayer(innerPlayer); 10266 } 10267 }); // the reason why we don't actually play the animation is 10268 // because all that a skipped player is designed to do is to 10269 // fire the start/done transition callback events 10270 10271 skippedPlayers.forEach(player => { 10272 if (player.parentPlayer) { 10273 player.syncPlayerEvents(player.parentPlayer); 10274 } else { 10275 player.destroy(); 10276 } 10277 }); // run through all of the queued removals and see if they 10278 // were picked up by a query. If not then perform the removal 10279 // operation right away unless a parent animation is ongoing. 10280 10281 for (let i = 0; i < allLeaveNodes.length; i++) { 10282 const element = allLeaveNodes[i]; 10283 const details = element[REMOVAL_FLAG]; 10284 removeClass(element, LEAVE_CLASSNAME); // this means the element has a removal animation that is being 10285 // taken care of and therefore the inner elements will hang around 10286 // until that animation is over (or the parent queried animation) 10287 10288 if (details && details.hasAnimation) continue; 10289 let players = []; // if this element is queried or if it contains queried children 10290 // then we want for the element not to be removed from the page 10291 // until the queried animations have finished 10292 10293 if (queriedElements.size) { 10294 let queriedPlayerResults = queriedElements.get(element); 10295 10296 if (queriedPlayerResults && queriedPlayerResults.length) { 10297 players.push(...queriedPlayerResults); 10298 } 10299 10300 let queriedInnerElements = this.driver.query(element, NG_ANIMATING_SELECTOR, true); 10301 10302 for (let j = 0; j < queriedInnerElements.length; j++) { 10303 let queriedPlayers = queriedElements.get(queriedInnerElements[j]); 10304 10305 if (queriedPlayers && queriedPlayers.length) { 10306 players.push(...queriedPlayers); 10307 } 10308 } 10309 } 10310 10311 const activePlayers = players.filter(p => !p.destroyed); 10312 10313 if (activePlayers.length) { 10314 removeNodesAfterAnimationDone(this, element, activePlayers
10314); 10315 } else { 10316 this.processLeaveNode(element); 10317 } 10318 } // this is required so the cleanup method doesn't remove them 10319 10320 10321 allLeaveNodes.length = 0; 10322 rootPlayers.forEach(player => { 10323 this.players.push(player); 10324 player.onDone(() => { 10325 player.destroy(); 10326 const index = this.players.indexOf(player); 10327 this.players.splice(index, 1); 10328 }); 10329 player.play(); 10330 }); 10331 return rootPlayers; 10332 } 10333 10334 elementContainsData(namespaceId, element) { 10335 let containsData = false; 10336 const details = element[REMOVAL_FLAG]; 10337 if (details && details.setForRemoval) containsData = true; 10338 if (this.playersByElement.has(element)) containsData = true; 10339 if (this.playersByQueriedElement.has(element)) containsData = true; 10340 if (this.statesByElement.has(element)) containsData = true; 10341 return this._fetchNamespace(namespaceId).elementContainsData(element) || containsData; 10342 } 10343 10344 afterFlush(callback) { 10345 this._flushFns.push(callback); 10346 } 10347 10348 afterFlushAnimationsDone(callback) { 10349 this._whenQuietFns.push(callback); 10350 } 10351 10352 _getPreviousPlayers(element, isQueriedElement, namespaceId, triggerName, toStateValue) { 10353 let players = []; 10354 10355 if (isQueriedElement) { 10356 const queriedElementPlayers = this.playersByQueriedElement.get(element); 10357 10358 if (queriedElementPlayers) { 10359 players = queriedElementPlayers; 10360 } 10361 } else { 10362 const elementPlayers = this.playersByElement.get(element); 10363 10364 if (elementPlayers) { 10365 const isRemovalAnimation = !toStateValue || toStateValue == VOID_VALUE; 10366 elementPlayers.forEach(player => { 10367 if (player.queued) return; 10368 if (!isRemovalAnimation && player.triggerName != triggerName) return; 10369 players.push(player); 10370 }); 10371 } 10372 } 10373 10374 if (namespaceId || triggerName) { 10375 players = players.filter(player => { 10376 if (namespaceId && namespaceId != player.namespaceId) return false; 10377 if (triggerName && triggerName != player.triggerName) return false; 10378 return true; 10379 }); 10380 } 10381 10382 return players; 10383 } 10384 10385 _beforeAnimationBuild(namespaceId, instruction, allPreviousPlayersMap) { 10386 const triggerName = instruction.triggerName; 10387 const rootElement = instruction.element; // when a removal animation occurs, ALL previous players are collected 10388 // and destroyed (even if they are outside of the current namespace) 10389 10390 const targetNameSpaceId = instruction.isRemovalTransition ? undefined : namespaceId; 10391 const targetTriggerName = instruction.isRemovalTransition ? undefined : triggerName; 10392
10393 for (const timelineInstruction of instruction.timelines) { 10394 const element = timelineInstruction.element; 10395 const isQueriedElement = element !== rootElement; 10396 const players = getOrSetDefaultValue(allPreviousPlayersMap, element, []); 10397 10398 const previousPlayers = this._getPreviousPlayers(element, isQueriedElement, targetNameSpaceId, targetTriggerName, instruction.toState); 10399 10400 previousPlayers.forEach(player => { 10401 const realPlayer = player.getRealPlayer(); 10402 10403 if (realPlayer.beforeDestroy) { 10404 realPlayer.beforeDestroy(); 10405 } 10406 10407 player.destroy(); 10408 players.push(player); 10409 }); 10410 } // this needs to be done so that the PRE/POST styles can be 10411 // computed properly without interfering with the previous animation 10412 10413 10414 eraseStyles(rootElement, instruction.fromStyles); 10415 } 10416 10417 _buildAnimation(namespaceId, instruction, allPreviousPlayersMap, skippedPlayersMap, preStylesMap, postStylesMap) { 10418 const triggerName = instruction.triggerName; 10419 const rootElement = instruction.element; // we first run this so that the previous animation player 10420 // data can be passed into the successive animation players 10421 10422 const allQueriedPlayers = []; 10423 const allConsumedElements = new Set(); 10424 const allSubElements = new Set(); 10425 const allNewPlayers = instruction.timelines.map(timelineInstru
10425ction => { 10426 const element = timelineInstruction.element; 10427 allConsumedElements.add(element); // FIXME (matsko): make sure to-be-removed animations are removed properly 10428 10429 const details = element[REMOVAL_FLAG]; 10430 if (details && details.removedBeforeQueried) return new _angular_animations__WEBPACK_IMPORTED_MODULE_1__.NoopAnimationPlayer(timelineInstruction.duration, timelineInstruction.delay); 10431 const isQueriedElement = element !== rootElement; 10432 const previousPlayers = flattenGroupPlayers((allPreviousPlayersMap.get(element) || EMPTY_PLAYER_ARRAY).map(p => p.getRealPlayer())).filter(p => { 10433 // the `element` is not apart of the AnimationPlayer definition, but 10434 // Mock/WebAnimations 10435 // use the element within their implementation. This will be added in Angular5 to 10436 // AnimationPlayer 10437 const pp = p; 10438 return pp.element ? pp.element === element : false; 10439 }); 10440 const preStyles = preStylesMap.get(element); 10441 const postStyles = postStylesMap.get(element); 10442 const keyframes = normalizeKeyframes$1(this.driver, this._normalizer, element, timelineInstru
vendor: 15,572 bytes, lines 10442-11008
10442ction.keyframes, preStyles, postStyles); 10443 10444 const player = this._buildPlayer(timelineInstruction, keyframes, previousPlayers); // this means that this particular player belongs to a sub trigger. It is 10445 // important that we match this player up with the corresponding (@trigger.listener) 10446 10447 10448 if (timelineInstruction.subTimeline && skippedPlayersMap) { 10449 allSubElements.add(element); 10450 } 10451 10452 if (isQueriedElement) { 10453 const wrappedPlayer = new TransitionAnimationPlayer(namespaceId, triggerName, element); 10454 wrappedPlayer.setRealPlayer(player); 10455 allQueriedPlayers.push(wrappedPlayer); 10456 } 10457 10458 return player; 10459 }); 10460 allQueriedPlayers.forEach(player => { 10461 getOrSetDefaultValue(this.playersByQueriedElement, player.element, []).push(player); 10462 player.onDone(() => deleteOrUnsetInMap(this.playersByQueriedElement, player.element, player)); 10463 }); 10464 allConsumedElements.forEach(element => addClass(element, NG_ANIMATING_CLASSNAME)); 10465 const player = optimizeGroupPlayer(allNewPlayers); 10466 player.onDestroy(() => { 10467 allConsumedElements.forEach(element => removeClass(element, NG_ANIMATING_CLASSNAME)); 10468 setStyles(rootElement, instruction.toStyles); 10469 }); // this basically makes all of the callbacks for sub element animations 10470 // be dependent on the upper players for when they finish 10471 10472 allSubElements.forEach(element => { 10473 getOrSetDefaultValue(skippedPlayersMap, element, []).push(player); 10474 }); 10475 return player; 10476 } 10477 10478 _buildPlayer(instruction, keyframes, previousPlayers) { 10479 if (keyframes.length > 0) { 10480 return this.driver.animate(instruction.element, keyframes, instruction.duration, instruction.delay, instruction.easing, previousPlayers); 10481 } // special case for when an empty transition|definition is provided 10482 // ... there is no point in rendering an empty animation 10483 10484 10485 return new _angular_animations__WEBPACK_IMPORTED_MODULE_1__.NoopAnimationPlayer(instruction.duration, instruction.delay); 10486 } 10487 10488} 10489 10490class TransitionAnimationPlayer { 10491 constructor(namespaceId, triggerName, element) { 10492 this.namespaceId = namespaceId; 10493 this.triggerName = triggerName; 10494 this.element = element; 10495 this._player = new _angular_animations__WEBPACK_IMPORTED_MODULE_1__.NoopAnimationPlayer(); 10496 this._containsRealPlayer = false; 10497 this._queuedCallbacks = new Map(); 10498 this.destroyed = false; 10499 this.markedForDestroy = false; 10500 this.disabled = false; 10501 this.queued = true; 10502 this.totalTime = 0; 10503 } 10504 10505 setRealPlayer(player) { 10506 if (this._containsRealPlayer) return; 10507 this._player = player; 10508 10509 this._queuedCallbacks.forEach((callbacks, phase) => { 10510 callbacks.forEach(callback => listenOnPlayer(player, phase, undefined, callback)); 10511 }); 10512 10513 this._queuedCallbacks.clear(); 10514 10515 this._containsRealPlayer = true; 10516 this.overrideTotalTime(player.totalTime); 10517 this.queued = false; 10518 } 10519 10520 getRealPlayer() { 10521 return this._player; 10522 } 10523 10524 overrideTotalTime(totalTime) { 10525 this.totalTime = totalTime; 10526 } 10527 10528 syncPlayerEvents(player) { 10529 const p = this._player; 10530 10531 if (p.triggerCallback) { 10532 player.onStart(() => p.triggerCallback('start')); 10533 } 10534 10535 player.onDone(() => this.finish()); 10536 player.onDestroy(() => this.destroy()); 10537 } 10538 10539 _queueEvent(name, callback) { 10540 getOrSetDefaultValue(this._queuedCallbacks, name, []).push(callback); 10541 } 10542 10543 onDone(fn) { 10544 if (this.queued) { 10545 this._queueEvent('done', fn); 10546 } 10547 10548 this._player.onDone(fn); 10549 } 10550 10551 onStart(fn) { 10552 if (this.queued) { 10553 this._queueEvent('start', fn); 10554 } 10555 10556 this._player.onStart(fn); 10557 } 10558 10559 onDestroy(fn) { 10560 if (this.queued) { 10561 this._queueEvent('destroy', fn); 10562 } 10563 10564 this._player.onDestroy(fn); 10565 } 10566 10567 init() { 10568 this._player.init(); 10569 } 10570 10571 hasStarted() { 10572 return this.queued ? false : this._player.hasStarted(); 10573 } 10574 10575 play() { 10576 !this.queued && this._player.play(); 10577 } 10578 10579 pause() { 10580 !this.queued && this._player.pause(); 10581 } 10582 10583 restart() { 10584 !this.queued && this._player.restart(); 10585 } 10586 10587 finish() { 10588 this._player.finish(); 10589 } 10590 10591 destroy() { 10592 this.destroyed = true; 10593 10594 this._player.destroy(); 10595 } 10596 10597 reset() { 10598 !this.queued && this._player.reset(); 10599 } 10600 10601 setPosition(p) { 10602 if (!this.queued) { 10603 this._player.setPosition(p); 10604 } 10605 } 10606 10607 getPosition() { 10608 return this.queued ? 0 : this._player.getPosition(); 10609 } 10610 /** @internal */ 10611 10612 10613 triggerCallback(phaseName) { 10614 const p = this._player; 10615 10616 if (p.triggerCallback) { 10617 p.triggerCallback(phaseName); 10618 } 10619 } 10620 10621} 10622 10623function deleteOrUnsetInMap(map, key, value) { 10624 let currentValues = map.get(key); 10625 10626 if (currentValues) { 10627 if (currentValues.length) { 10628 const index = currentValues.indexOf(value); 10629 currentValues.splice(index, 1); 10630 } 10631 10632 if (currentValues.length == 0) { 10633 map.delete(key); 10634 } 10635 } 10636 10637 return currentValues; 10638} 10639 10640function normalizeTriggerValue(value) { 10641 // we use `!= null` here because it's the most simple 10642 // way to test against a "falsy" value without mixing 10643 // in empty strings or a zero value. DO NOT OPTIMIZE. 10644 return value != null ? value : null; 10645} 10646 10647function isElementNode(node) { 10648 return node && node['nodeType'] === 1; 10649} 10650 10651function isTriggerEventValid(eventName) { 10652 return eventName == 'start' || eventName == 'done'; 10653} 10654 10655function cloakElement(element, value) { 10656 const oldValue = element.style.display; 10657 element.style.display = value != null ? value : 'none'; 10658 return oldValue; 10659} 10660 10661function cloakAndComputeStyles(valuesMap, driver, elements, elementPropsMap, defaultStyle) { 10662 const cloakVals = []; 10663 elements.forEach(element => cloakVals.push(cloakElement(element))); 10664 const failedElements = []; 10665 elementPropsMap.forEach((props, element) => { 10666 const styles = new Map(); 10667 props.forEach(prop => { 10668 const value = driver.computeStyle(element, prop, defaultStyle); 10669 styles.set(prop, value); // there is no easy way to detect this because a sub element could be removed 10670 // by a parent animation element being detached. 10671 10672 if (!value || value.length == 0) { 10673 element[REMOVAL_FLAG] = NULL_REMOVED_QUERIED_STATE; 10674 failedElements.push(element); 10675 } 10676 }); 10677 valuesMap.set(element, styles); 10678 }); // we use a index variable here since Set.forEach(a, i) does not return 10679 // an index value for the closure (but instead just the value) 10680 10681 let i = 0; 10682 elements.forEach(element => cloakElement(element, cloakVals[i++])); 10683 return failedElements; 10684} 10685/* 10686Since the Angular renderer code will return a collection of inserted 10687nodes in all areas of a DOM tree, it's up to this algorithm to figure 10688out which nodes are roots for each animation @trigger. 10689 10690By placing each inserted node into a Set and traversing upwards, it 10691is possible to find the @trigger elements and well any direct *star 10692insertion nodes, if a @trigger root is found then the enter element 10693is placed into the Map[@trigger] spot. 10694 */ 10695 10696 10697function buildRootMap(roots, nodes) { 10698 const rootMap = new Map(); 10699 roots.forEach(root => rootMap.set(root, [])); 10700 if (nodes.length == 0) return rootMap; 10701 const NULL_NODE = 1; 10702 const nodeSet = new Set(nodes); 10703 const localRootMap = new Map(); 10704 10705 function getRoot(node) { 10706 if (!node) return NULL_NODE; 10707 let root = localRootMap.get(node); 10708 if (root) return root; 10709 const parent = node.parentNode; 10710 10711 if (rootMap.has(parent)) { 10712 // ngIf inside @trigger 10713 root = parent; 10714 } else if (nodeSet.has(parent)) { 10715 // ngIf inside ngIf 10716 root = NULL_NODE; 10717 } else { 10718 // recurse upwards 10719 root = getRoot(parent); 10720 } 10721 10722 localRootMap.set(node, root); 10723 return root; 10724 } 10725 10726 nodes.forEach(node => { 10727 const root = getRoot(node); 10728 10729 if (root !== NULL_NODE) { 10730 rootMap.get(root).push(node); 10731 } 10732 }); 10733 return rootMap; 10734} 10735 10736function addClass(element, className) { 10737 element.classList?.add(className); 10738} 10739 10740function removeClass(element, className) { 10741 element.classList?.remove(className); 10742} 10743 10744function removeNodesAfterAnimationDone(engine, element, players) { 10745 optimizeGroupPlayer(players).onDone(() => engine.processLeaveNode(element)); 10746} 10747 10748function flattenGroupPlayers(players) { 10749 const finalPlayers = []; 10750 10751 _flattenGroupPlayersRecur(players, finalPlayers); 10752 10753 return finalPlayers; 10754} 10755 10756function _flattenGroupPlayersRecur(players, finalPlayers) { 10757 for (let i = 0; i < players.length; i++) { 10758 const player = players[i]; 10759 10760 if (player instanceof _angular_animations__WEBPACK_IMPORTED_MODULE_1__["ɵAnimationGroupPlayer"]) { 10761 _flattenGroupPlayersRecur(player.players, finalPlayers); 10762 } else { 10763 finalPlayers.push(player); 10764 } 10765 } 10766} 10767 10768function objEquals(a, b) { 10769 const k1 = Object.keys(a); 10770 const k2 = Object.keys(b); 10771 if (k1.length != k2.length) return false; 10772 10773 for (let i = 0; i < k1.length; i++) { 10774 const prop = k1[i]; 10775 if (!b.hasOwnProperty(prop) || a[prop] !== b[prop]) return false; 10776 } 10777 10778 return true; 10779} 10780 10781function replacePostStylesAsPre(element, allPreStyleElements, allPostStyleElements) { 10782 const postEntry = allPostStyleElements.get(element); 10783 if (!postEntry) return false; 10784 let preEntry = allPreStyleElements.get(element); 10785 10786 if (preEntry) { 10787 postEntry.forEach(data => preEntry.add(data)); 10788 } else { 10789 allPreStyleElements.set(element, postEntry); 10790 } 10791 10792 allPostStyleElements.delete(element); 10793 return true; 10794} 10795 10796class AnimationEngine { 10797 constructor(bodyNode, _driver, _normalizer) { 10798 this.bodyNode = bodyNode; 10799 this._driver = _driver; 10800 this._normalizer = _normalizer; 10801 this._triggerCache = {}; // this method is designed to be overridden by the code that uses this engine 10802 10803 this.onRemovalComplete = (element, context) => {}; 10804 10805 this._transitionEngine = new TransitionAnimationEngine(bodyNode, _driver, _normalizer); 10806 this._timelineEngine = new TimelineAnimationEngine(bodyNode, _driver, _normalizer); 10807 10808 this._transitionEngine.onRemovalComplete = (element, context) => this.onRemovalComplete(element, context); 10809 } 10810 10811 registerTrigger(componentId, namespaceId, hostElement, name, metadata) { 10812 const cacheKey = componentId + '-' + name; 10813 let trigger = this._triggerCache[cacheKey]; 10814 10815 if (!trigger) { 10816 const errors = []; 10817 const warnings = []; 10818 const ast = buildAnimationAst(this._driver, metadata, errors, warnings); 10819 10820 if (errors.length) { 10821 throw triggerBuildFailed(name, errors); 10822 } 10823 10824 if (warnings.length) { 10825 warnTriggerBuild(name, warnings); 10826 } 10827 10828 trigger = buildTrigger(name, ast, this._normalizer); 10829 this._triggerCache[cacheKey] = trigger; 10830 } 10831 10832 this._transitionEngine.registerTrigger(namespaceId, name, trigger); 10833 } 10834 10835 register(namespaceId, hostElement) { 10836 this._transitionEngine.register(namespaceId, hostElement); 10837 } 10838 10839 destroy(namespaceId, context) { 10840 this._transitionEngine.destroy(namespaceId, context); 10841 } 10842 10843 onInsert(namespaceId, element, parent, insertBefore) { 10844 this._transitionEngine.insertNode(namespaceId, element, parent, insertBefore); 10845 } 10846 10847 onRemove(namespaceId, element, context, isHostElement) { 10848 this._transitionEngine.removeNode(namespaceId, element, isHostElement || false, context); 10849 } 10850 10851 disableAnimations(element, disable) { 10852 this._transitionEngine.markElementAsDisabled(element, disable); 10853 } 10854 10855 process(namespaceId, element, property, value) { 10856 if (property.charAt(0) == '@') { 10857 const [id, action] = parseTimelineCommand(property); 10858 const args = value; 10859 10860 this._timelineEngine.command(id, element, action, args); 10861 } else { 10862 this._transitionEngine.trigger(namespaceId, element, property, value); 10863 } 10864 } 10865 10866 listen(namespaceId, element, eventName, eventPhase, callback) { 10867 // @@listen 10868 if (eventName.charAt(0) == '@') { 10869 const [id, action] = parseTimelineCommand(eventName); 10870 return this._timelineEngine.listen(id, element, action, callback); 10871 } 10872 10873 return this._transitionEngine.listen(namespaceId, element, eventName, eventPhase, callback); 10874 } 10875 10876 flush(microtaskId = -1) { 10877 this._transitionEngine.flush(microtaskId); 10878 } 10879 10880 get players() { 10881 return this._transitionEngine.players.concat(this._timelineEngine.players); 10882 } 10883 10884 whenRenderingDone() { 10885 return this._transitionEngine.whenRenderingDone(); 10886 } 10887 10888} 10889/** 10890 * Returns an instance of `SpecialCasedStyles` if and when any special (non animateable) styles are 10891 * detected. 10892 * 10893 * In CSS there exist properties that cannot be animated within a keyframe animation 10894 * (whether it be via CSS keyframes or web-animations) and the animation implementation 10895 * will ignore them. This function is designed to detect those special cased styles and 10896 * return a container that will be executed at the start and end of the animation. 10897 * 10898 * @returns an instance of `SpecialCasedStyles` if any special styles are detected otherwise `null` 10899 */ 10900 10901 10902function packageNonAnimatableStyles(element, styles) { 10903 let startStyles = null; 10904 let endStyles = null; 10905 10906 if (Array.isArray(styles) && styles.length) { 10907 startStyles = filterNonAnimatableStyles(styles[0]); 10908 10909 if (styles.length > 1) { 10910 endStyles = filterNonAnimatableStyles(styles[styles.length - 1]); 10911 } 10912 } else if (styles instanceof Map) { 10913 startStyles = filterNonAnimatableStyles(styles); 10914 } 10915 10916 return startStyles || endStyles ? new SpecialCasedStyles(element, startStyles, endStyles) : null; 10917} 10918/** 10919 * Designed to be executed during a keyframe-based animation to apply any special-cased styles. 10920 * 10921 * When started (when the `start()` method is run) then the provided `startStyles` 10922 * will be applied. When finished (when the `finish()` method is called) the 10923 * `endStyles` will be applied as well any any starting styles. Finally when 10924 * `destroy()` is called then all styles will be removed. 10925 */ 10926 10927 10928class SpecialCasedStyles { 10929 constructor(_element, _startStyles, _endStyles) { 10930 this._element = _element; 10931 this._startStyles = _startStyles; 10932 this._endStyles = _endStyles; 10933 this._state = 0 10934 /* SpecialCasedStylesState.Pending */ 10935 ; 10936 let initialStyles = SpecialCasedStyles.initialStylesByElement.get(_element); 10937 10938 if (!initialStyles) { 10939 SpecialCasedStyles.initialStylesByElement.set(_element, initialStyles = new Map()); 10940 } 10941 10942 this._initialStyles = initialStyles; 10943 } 10944 10945 start() { 10946 if (this._state < 1 10947 /* SpecialCasedStylesState.Started */ 10948 ) { 10949 if (this._startStyles) { 10950 setStyles(this._element, this._startStyles, this._initialStyles); 10951 } 10952 10953 this._state = 1 10954 /* SpecialCasedStylesState.Started */ 10955 ; 10956 } 10957 } 10958 10959 finish() { 10960 this.start(); 10961 10962 if (this._state < 2 10963 /* SpecialCasedStylesState.Finished */ 10964 ) { 10965 setStyles(this._element, this._initialStyles); 10966 10967 if (this._endStyles) { 10968 setStyles(this._element, this._endStyles); 10969 this._endStyles = null; 10970 } 10971 10972 this._state = 1 10973 /* SpecialCasedStylesState.Started */ 10974 ; 10975 } 10976 } 10977 10978 destroy() { 10979 this.finish(); 10980 10981 if (this._state < 3 10982 /* SpecialCasedStylesState.Destroyed */ 10983 ) { 10984 SpecialCasedStyles.initialStylesByElement.delete(this._element); 10985 10986 if (this._startStyles) { 10987 eraseStyles(this._element, this._startStyles); 10988 this._endStyles = null; 10989 } 10990 10991 if (this._endStyles) { 10992 eraseStyles(this._element, this._endStyles); 10993 this._endStyles = null; 10994 } 10995 10996 setStyles(this._element, this._initialStyles); 10997 this._state = 3 10998 /* SpecialCasedStylesState.Destroyed */ 10999 ; 11000 } 11001 } 11002 11003} 11004 11005SpecialCasedStyles.initialStylesByElement = /* @__PURE__ */new WeakMap(); 11006 11007function filterNonAnimatableStyles(styles) { 11008 let result = null;
11009 styles.forEach((val, prop) => { 11010 if (isNonAnimatableStyle(prop)) { 11011 result = result || new Map(); 11012 result.set(prop, val); 11013 } 11014 }); 11015 return result; 11016} 11017 11018function isNonAnimatableStyle(prop) { 11019 return prop === 'display' || prop === 'position'; 11020} 11021 11022class WebAnimationsPlayer { 11023 constructor(element, keyframes, options, _specialStyles) { 11024 this.element = element; 11025 this.keyframes = keyframes; 11026 this.options = options; 11027 this._specialStyles = _specialStyles; 11028 this._onDoneFns = []; 11029 this._onStartFns = []; 11030 this._onDestroyFns = []; 11031 this._initialized = false; 11032 this._finished = false; 11033 this._started = false; 11034 this._destroyed = false; // the following original fns are persistent copies of the _onStartFns and _onDoneFns 11035 // and are used to reset the fns to their original values upon reset() 11036 // (since the _onStartFns and _onDoneFns get deleted after they are called) 11037 11038 this._originalOnDoneFns = []; 11039 this._originalOnStartFns = []; 11040 this.time = 0; 11041 this.parentPlayer = null; 11042 this.currentSnapshot = new Map(); 11043 this._duration = options['duration']; 11044 this._delay = options['delay'] || 0; 11045 this.time = this._duration + this._delay; 11046 } 11047 11048 _onFinish() { 11049 if (!this._finished) { 11050 this._finished = true; 11051 11052 this._onDoneFns.forEach(fn => fn()); 11053 11054 this._onDoneFns = []; 11055 } 11056 } 11057 11058 init() { 11059 this._buildPlayer(); 11060 11061 this._preparePlayerBeforeStart(); 11062 } 11063 11064 _buildPlayer() { 11065 if (this._initialized) return; 11066 this._initialized = true; 11067 const keyframes = this.keyframes; 11068 this.domPlayer = this._triggerWebAnimation(this.element, keyframes, this.options); 11069 this._finalKeyframe = keyframes.length ? keyframes[keyframes.length - 1] : new Map(); 11070 this.domPlayer.addEventListener('finish', () => this._onFinish()); 11071 } 11072 11073 _preparePlayerBeforeStart() { 11074 // this is required so that the player doesn't start to animate right away 11075 if (this._delay) { 11076 this._resetDomPlayerState(); 11077 } else { 11078 this.domPlayer.pause(); 11079 } 11080 } 11081 11082 _convertKeyframesToObject(keyframes) { 11083 const kfs = []; 11084 keyframes.forEach(frame => { 11085 kfs.push(Object.fromEntries(frame)); 11086 }); 11087 return kfs; 11088 } 11089 /** @internal */ 11090 11091 11092 _triggerWebAnimation(element, keyframes, options) { 11093 // jscompiler doesn't seem to know animate is a native property because it's not fully 11094 // supported yet across common browsers (we polyfill it for Edge/Safari) [CL #143630929] 11095 return element['animate'](this._convertKeyframesToObject(keyframes), options); 11096 } 11097 11098 onStart(fn) { 11099 this._originalOnStartFns.push(fn); 11100 11101 this._onStartFns.push(fn); 11102 } 11103 11104 onDone(fn) { 11105 this._originalOnDoneFns.push(fn); 11106 11107 this._onDoneFns.push(fn); 11108 } 11109 11110 onDestroy(fn) { 11111 this._onDestroyFns.push(fn); 11112 } 11113 11114 play() { 11115 this._buildPlayer(); 11116 11117 if (!this.hasStarted()) { 11118 this._onStartFns.forEach(fn => fn()); 11119 11120 this._onStartFns = []; 11121 this._started = true; 11122 11123 if (this._specialStyles) { 11124 this._specialStyles.start(); 11125 } 11126 } 11127 11128 this.domPlayer.play(); 11129 } 11130 11131 pause() { 11132 this.init(); 11133 this.domPlayer.pause(); 11134 } 11135 11136 finish() { 11137 this.init(); 11138 11139 if (this._specialStyles) { 11140 this._specialStyles.finish(); 11141 } 11142 11143 this._onFinish(); 11144 11145 this.domPlayer.finish(); 11146 } 11147 11148 reset() { 11149 this._resetDomPlayerState(); 11150 11151 this._destroyed = false; 11152 this._finished = false; 11153 this._started = false; 11154 this._onStartFns = this._originalOnStartFns; 11155 this._onDoneFns = this._originalOnDoneFns; 11156 } 11157 11158 _resetDomPlayerState() { 11159 if (this.domPlayer) { 11160 this.domPlayer.cancel(); 11161 } 11162 } 11163 11164 restart() { 11165 this.reset(); 11166 this.play(); 11167 } 11168 11169 hasStarted() { 11170 return this._started; 11171 } 11172 11173 destroy() { 11174 if (!this._destroyed) { 11175 this._destroyed = true; 11176 11177 this._resetDomPlayerState(); 11178 11179 this._onFinish(); 11180 11181 if (this._specialStyles) { 11182 this._specialStyles.destroy(); 11183 } 11184 11185 this._onDestroyFns.forEach(fn => fn()); 11186 11187 this._onDestroyFns = []; 11188 } 11189 } 11190 11191 setPosition(p) { 11192 if (this.domPlayer === undefined) { 11193 this.init(); 11194 } 11195 11196 this.domPlayer.currentTime = p * this.time; 11197 } 11198 11199 getPosition() { 11200 return this.domPlayer.currentTime / this.time; 11201 } 11202 11203 get totalTime() { 11204 return this._delay + this._duration; 11205 } 11206 11207 beforeDestroy() { 11208 const styles = new Map(); 11209 11210 if (this.hasStarted()) { 11211 // note: this code is invoked only when the `play` function was called prior to this 11212 // (thus `hasStarted` returns true), this implies that the code that initializes 11213 // `_finalKeyframe` has also been executed and the non-null assertion can be safely used here 11214 const finalKeyframe = this._finalKeyframe; 11215 finalKeyframe.forEach((val, prop) => { 11216 if (prop !== 'offset') { 11217 styles.set(prop, this._finished ? val : computeStyle(this.element, prop)); 11218 } 11219 }); 11220 } 11221 11222 this.currentSnapshot = styles; 11223 } 11224 /** @internal */ 11225 11226 11227 triggerCallback(phaseName) { 11228 const methods = phaseName === 'start' ? this._onStartFns : this._onDoneFns; 11229 methods.forEach(fn => fn()); 11230 methods.length = 0; 11231 } 11232 11233} 11234 11235class WebAnimationsDriver { 11236 validateStyleProperty(prop) { 11237 // Perform actual validation in dev mode only, in prod mode this check is a noop. 11238 if (typeof ngDevMode === 'undefined' || ngDevMode) { 11239 return validateStyleProperty(prop); 11240 } 11241 11242 return true; 11243 } 11244 11245 validateAnimatableStyleProperty(prop) { 11246 // Perform actual validation in dev mode only, in prod mode this check is a noop. 11247 if (typeof ngDevMode === 'undefined' || ngDevMode) { 11248 const cssProp = camelCaseToDashCase(prop); 11249 return validateWebAnimatableStyleProperty(cssProp); 11250 } 11251 11252 return true; 11253 } 11254 11255 matchesElement(_element, _selector) { 11256 // This method is deprecated and no longer in use so we return false. 11257 return false;
11258 } 11259 11260 containsElement(elm1, elm2) { 11261 return containsElement(elm1, elm2); 11262 } 11263 11264 getParentElement(element) { 11265 return getParentElement(element); 11266 } 11267 11268 query(element, selector, multi) { 11269 return invokeQuery(element, selector, multi); 11270 } 11271 11272 computeStyle(element, prop, defaultValue) { 11273 return window.getComputedStyle(element)[prop]; 11274 } 11275 11276 animate(element, keyframes, duration, delay, easing, previousPlayers = []) { 11277 const fill = delay == 0 ? 'both' : 'forwards'; 11278 const playerOptions = { 11279 duration, 11280 delay, 11281 fill 11282 }; // we check for this to avoid having a null|undefined value be present 11283 // for the easing (which results in an error for certain browsers #9752) 11284 11285 if (easing) { 11286 playerOptions['easing'] = easing; 11287 } 11288 11289 const previousStyles = new Map(); 11290 const previousWebAnimationPlayers = previousPlayers.filter(player => player instanceof WebAnimationsPlayer); 11291 11292 if (allowPreviousPlayerStylesMerge(duration, delay)) { 11293 previousWebAnimationPlayers.forEach(player => { 11294 player.currentSnapshot.forEach((val, prop) => previousStyles.set(prop, val)); 11295 }); 11296 } 11297 11298 let _keyframes = normalizeKeyframes(keyframes).map(styles => copyStyles(styles)); 11299 11300 _keyframes = balancePreviousStylesIntoKeyframes(element, _keyframes, previousStyles); 11301 const specialStyles = packageNonAnimatableStyles(element, _keyframes); 11302 return new WebAnimationsPlayer(element, _keyframes, playerOptions, specialStyles); 11303 } 11304 11305} 11306/** 11307 * @license 11308 * Copyright Google LLC All Rights Reserved. 11309 * 11310 * Use of this source code is governed by an MIT-style license that can be 11311 * found in the LICENSE file at https://angular.io/license 11312 */ 11313 11314/** 11315 * @license 11316 * Copyright Google LLC All Rights Reserved. 11317 * 11318 * Use of this source code is governed by an MIT-style license that can be 11319 * found in the LICENSE file at https://angular.io/license 11320 */ 11321 11322/** 11323 * @license 11324 * Copyright Google LLC All Rights Reserved. 11325 * 11326 * Use of this source code is governed by an MIT-style license that can be 11327 * found in the LICENSE file at https://angular.io/license 11328 */ 11329 11330/** 11331 * @license 11332 * Copyright Google LLC All Rights Reserved. 11333 * 11334 * Use of this source code is governed by an MIT-style license that can be 11335 * found in the LICENSE file at https://angular.io/license 11336 */ 11337 11338/** 11339 * Generated bundle index. Do not edit. 11340 */ 11341 11342 11343 11344 11345/***/ }), 11346 11347/***/ 4666: 11348/*!**********************************************************!*\ 11349 !*** ./node_modules/@angular/common/fesm2020/common.mjs ***! 11350 \**********************************************************/ 11351/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 11352 11353__webpack_require__.r(__webpack_exports__); 11354/* harmony export */ __webpack_require__.d(__webpack_exports__, { 11355/* harmony export */ "APP_BASE_HREF": () => (/* binding */ APP_BASE_HREF), 11356/* harmony export */ "AsyncPipe": () => (/* binding */ AsyncPipe), 11357/* harmony export */ "CommonModule": () => (/* binding */ CommonModule), 11358/* harmony export */ "CurrencyPipe": () => (/* binding */ CurrencyPipe), 11359/* harmony export */ "DATE_PIPE_DEFAULT_TIMEZONE": () => (/* binding */ DATE_PIPE_DEFAULT_TIMEZONE), 11360/* harmony export */ "DOCUMENT": () => (/* binding */ DOCUMENT), 11361/* harmony export */ "DatePipe": () => (/* binding */ DatePipe), 11362/* harmony export */ "DecimalPipe": () => (/* binding */ DecimalPipe), 11363/* harmony export */ "FormStyle": () => (/* binding */ FormStyle), 11364/* harmony export */ "FormatWidth": () => (/* binding */ FormatWidth), 11365/* harmony export */ "HashLocationStrategy": () => (/* binding */ HashLocationStrategy), 11366/* harmony export */ "I18nPluralPipe": () => (/* binding */ I18nPluralPipe), 11367/* harmony export */ "I18nSelectPipe": () => (/* binding */ I18nSelectPipe), 11368/* harmony export */ "IMAGE_LOADER": () => (/* binding */ IMAGE_LOADER), 11369/* harmony export */ "JsonPipe": () => (/* binding */ JsonPipe), 11370/* harmony export */ "KeyValuePipe": () => (/* binding */ KeyValuePipe), 11371/* harmony export */ "LOCATION_INITIALIZED": () => (/* binding */ LOCATION_INITIALIZED), 11372/* harmony export */ "Location": () => (/* binding */ Location), 11373/* harmony export */ "LocationStrategy": () => (/* binding */ LocationStrategy), 11374/* harmony export */ "LowerCasePipe": () => (/* binding */ LowerCasePipe), 11375/* harmony export */ "NgClass": () => (/* binding */ NgClass), 11376/* harmony export */ "NgComponentOutlet": () => (/* binding */ NgComponentOutlet), 11377/* harmony export */ "NgFor": () => (/* binding */ NgForOf), 11378/* harmony export */ "NgForOf": () => (/* binding */ NgForOf), 11379/* harmony export */ "NgForOfContext": () => (/* binding */ NgForOfContext), 11380/* harmony export */ "NgIf": () => (/* binding */ NgIf), 11381/* harmony export */ "NgIfContext": () => (/* binding */ NgIfContext), 11382/* harmony export */ "NgLocaleLocalization": () => (/* binding */ NgLocaleLocalization), 11383/* harmony export */ "NgLocalization": () => (/* binding */ NgLocalization), 11384/* harmony export */ "NgOptimizedImage": () => (/* binding */ NgOptimizedImage), 11385/* harmony export */ "NgPlural": () => (/* binding */ NgPlural), 11386/* harmony export */ "NgPluralCase": () => (/* binding */ NgPluralCase), 11387/* harmony export */ "NgStyle": () => (/* binding */ NgStyle), 11388/* harmony export */ "NgSwitch": () => (/* binding */ NgSwitch), 11389/* harmony export */ "NgSwitchCase": () => (/* binding */ NgSwitchCase), 11390/* harmony export */ "NgSwitchDefault": () => (/* binding */ NgSwitchDefault), 11391/* harmony export */ "NgTemplateOutlet": () => (/* binding */ NgTemplateOutlet), 11392/* harmony export */ "NumberFormatStyle": () => (/* binding */ NumberFormatStyle), 11393/* harmony export */ "NumberSymbol": () => (/* binding */ NumberSymbol), 11394/* harmony export */ "PRECONNECT_CHECK_BLOCKLIST": () => (/* binding */ PRECONNECT_CHECK_BLOCKLIST), 11395/* harmony export */ "PathLocationStrategy": () => (/* binding */ PathLocationStrategy), 11396/* harmony export */ "PercentPipe": () => (/* binding */ PercentPipe), 11397/* harmony export */ "PlatformLocation": () => (/* binding */ PlatformLocation), 11398/* harmony export */ "Plural": () => (/* binding */ Plural), 11399/* harmony export */ "SlicePipe": () => (/* binding */ SlicePipe), 11400/* harmony export */ "TitleCasePipe": () => (/* binding */ TitleCasePipe), 11401/* harmony export */ "TranslationWidth": () => (/* binding */ TranslationWidth), 11402/* harmony export */ "UpperCasePipe": () => (/* binding */ UpperCasePipe), 11403/* harmony export */ "VERSION": () => (/* binding */ VERSION), 11404/* harmony export */ "ViewportScroller": () => (/* binding */ ViewportScroller), 11405/* harmony export */ "WeekDay": () => (/* binding */ WeekDay), 11406/* harmony export */ "XhrFactory": () => (/* binding */ XhrFactory), 11407/* harmony export */ "formatCurrency": () => (/* binding */ formatCurrency), 11408/* harmony export */ "formatDate": () => (/* binding */ formatDate), 11409/* harmony export */ "formatNumber": () => (/* binding */ formatNumber), 11410/* harmony export */ "formatPercent": () => (/* binding */ formatPercent), 11411/* harmony export */ "getCurrencySymbol": () => (/* binding */ getCurrencySymbol), 11412/* harmony export */ "getLocaleCurrencyCode": () => (/* binding */ getLocaleCurrencyCode), 11413/* harmony export */ "getLocaleCurrencyName": () => (/* binding */ getLocaleCurrencyName), 11414/* harmony export */ "getLocaleCurrencySymbol": () => (/* binding */ getLocaleCurrencySymbol), 11415/* harmony export */ "getLocaleDateFormat": () => (/* binding */ getLocaleDateFormat), 11416/* harmony export */ "getLocaleDateTimeFormat": () => (/* binding */ getLocaleDateTimeFormat), 11417/* harmony export */ "getLocaleDayNames": () => (/* binding */ getLocaleDayNames), 11418/* harmony export */ "getLocaleDayPeriods": () => (/* binding */ getLocaleDayPeriods), 11419/* harmony export */ "getLocaleDirection": () => (/* binding */ getLocaleDirection), 11420/* harmony export */ "getLocaleEraNames": () => (/* binding */ getLocaleEraNames), 11421/* harmony export */ "getLocaleExtraDayPeriodRules": () => (/* binding */ getLocaleExtraDayPeriodRules), 11422/* harmony export */ "getLocaleExtraDayPeriods": () => (/* binding */ getLocaleExtraDayPeriods), 11423/* harmony export */ "getLocaleFirstDayOfWeek": () => (/* binding */ getLocaleFirstDayOfWeek), 11424/* harmony export */ "getLocaleId": () => (/* binding */ getLocaleId), 11425/* harmony export */ "getLocaleMonthNames": () => (/* binding */ getLocaleMonthNames), 11426/* harmony export */ "getLocaleNumberFormat": () => (/* binding */ getLocaleNumberFormat), 11427/* harmony export */ "getLocaleNumberSymbol": () => (/* binding */ getLocaleNumberSymbol), 11428/* harmony export */ "getLocalePluralCase": () => (/* binding */ getLocalePluralCase), 11429/* harmony export */ "getLocaleTimeFormat": () => (/* binding */ getLocaleTimeFormat), 11430/* harmony export */ "getLocaleWeekEndRange": () => (/* binding */ getLocaleWeekEndRange), 11431/* harmony export */ "getNumberOfCurrencyDigits": () => (/* binding */ getNumberOfCurrencyDigits), 11432/* harmony export */ "isPlatformBrowser": () => (/* binding */ isPlatformBrowser), 11433/* harmony export */ "isPlatformServer": () => (/* binding */ isPlatformServer), 11434/* harmony export */ "isPlatformWorkerApp": () => (/* binding */ isPlatformWorkerApp), 11435/* harmony export */ "isPlatformWorkerUi": () => (/* binding */ isPlatformWorkerUi), 11436/* harmony export */ "provideCloudflareLoader": () => (/* binding */ provideCloudflareLoader), 11437/* harmony export */ "provideCloudinaryLoader": () => (/* binding */ provideCloudinaryLoader), 11438/* harmony export */ "provideImageKitLoader": () => (/* binding */ provideImageKitLoader), 11439/* harmony export */ "provideImgixLoader": () => (/* binding */ provideImgixLoader), 11440/* harmony export */ "registerLocaleData": () => (/* binding */ registerLocaleData), 11441/* harmony export */ "ɵBrowserPlatformLocation": () => (/* binding */ BrowserPlatformLocation), 11442/* harmony export */ "ɵDomAdapter": () => (/* binding */ DomAdapter), 11443/* harmony export */ "ɵNullViewportScroller": () => (/* binding */ NullViewportScroller), 11444/* harmony export */ "ɵPLATFORM_BROWSER_ID": () => (/* binding */ PLATFORM_BROWSER_ID), 11445/* harmony export */ "ɵPLATFORM_SERVER_ID": () => (/* binding */ PLATFORM_SERVER_ID), 11446/* harmony export */ "ɵPLATFORM_WORKER_APP_ID": () => (/* binding */ PLATFORM_WORKER_APP_ID), 11447/* harmony export */ "ɵPLATFORM_WORKER_UI_ID": () => (/* binding */ PLATFORM_WORKER_UI_ID), 11448/* harmony export */ "ɵgetDOM": () => (/* binding */ getDOM), 11449/* harmony export */ "ɵparseCookieValue": () => (/* binding */ parseCookieValue), 11450/* harmony export */ "ɵsetRootDomAdapter": () => (/* binding */ setRootDomAdapter) 11451/* harmony export */ }); 11452/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 2560); 11453/** 11454 * @license Angular v14.2.10 11455 * (c) 2010-2022 Google LLC. https://angular.io/ 11456 * License: MIT 11457 */ 11458 11459 11460/** 11461 * @license 11462 * Copyright Google LLC All Rights Reserved. 11463 * 11464 * Use of this source code is governed by an MIT-style license that can be 11465 * found in the LICENSE file at https://angular.io/license 11466 */ 11467 11468let _DOM = null; 11469 11470function getDOM() { 11471 return _DOM; 11472} 11473 11474function setDOM(adapter) { 11475 _DOM = adapter; 11476} 11477 11478function setRootDomAdapter(adapter) { 11479 if (!_DOM) { 11480 _DOM = adapter; 11481 } 11482} 11483/* tslint:disable:requireParameterType */ 11484 11485/** 11486 * Provides DOM operations in an environment-agnostic way. 11487 * 11488 * @security Tread carefully! Interacting with the DOM directly is dangerous and 11489 * can introduce XSS risks. 11490 */ 11491 11492 11493class DomAdapter {} 11494/** 11495 * @license 11496 * Copyright Google LLC All Rights Reserved. 11497 * 11498 * Use of this source code is governed by an MIT-style license that can be 11499 * found in the LICENSE file at https://angular.io/license 11500 */ 11501 11502/** 11503 * A DI Token representing the main rendering context. In a browser this is the DOM Document. 11504 *
11505 * Note: Document might not be available in the Application Context when Application and Rendering 11506 * Contexts are not the same (e.g. when running the application in a Web Worker). 11507 * 11508 * @publicApi 11509 */ 11510 11511 11512const DOCUMENT = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('DocumentToken'); 11513/** 11514 * @license 11515 * Copyright Google LLC All Rights Reserved. 11516 * 11517 * Use of this source code is governed by an MIT-style license that can be 11518 * found in the LICENSE file at https://angular.io/license 11519 */ 11520 11521/** 11522 * This class should not be used directly by an application developer. Instead, use 11523 * {@link Location}. 11524 * 11525 * `PlatformLocation` encapsulates all calls to DOM APIs, which allows the Router to be 11526 * platform-agnostic. 11527 * This means that we can have different implementation of `PlatformLocation` for the different 11528 * platforms that Angular supports. For example, `@angular/platform-browser` provides an 11529 * implementation specific to the browser environment, while `@angular/platform-server` provides 11530 * one suitable for use with server-side rendering. 11531 * 11532 * The `PlatformLocation` class is used directly by all implementations of {@link LocationStrategy} 11533 * when they need to interact with the DOM APIs like pushState, popState, etc. 11534 * 11535 * {@link LocationStrategy} in turn is used by the {@link Location} service which is used directly 11536 * by the {@link Router} in order to navigate between routes. Since all interactions between {@link 11537 * Router} / 11538 * {@link Location} / {@link LocationStrategy} and DOM APIs flow through the `PlatformLocation` 11539 * class, they are all platform-agnostic. 11540 * 11541 * @publicApi 11542 */ 11543 11544class PlatformLocation { 11545 historyGo(relativePosition) { 11546 throw new Error('Not implemented'); 11547 } 11548 11549} 11550 11551PlatformLocation.ɵfac = function PlatformLocation_Factory(t) { 11552 return new (t || PlatformLocation)(); 11553}; 11554 11555PlatformLocation.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 11556 token: PlatformLocation, 11557 factory: function () { 11558 return useBrowserPlatformLocation(); 11559 }, 11560 providedIn: 'platform' 11561}); 11562 11563(function () { 11564 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](PlatformLocation, [{ 11565 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 11566 args: [{ 11567 providedIn: 'platform', 11568 // See #23917 11569 useFactory: useBrowserPlatformLocation 11570 }] 11571 }], null, null); 11572})(); 11573 11574function useBrowserPlatformLocation() { 11575 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(BrowserPlatformLocation); 11576} 11577/** 11578 * @description 11579 * Indicates when a location is initialized. 11580 * 11581 * @publicApi 11582 */ 11583 11584 11585const LOCATION_INITIALIZED = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('Location Initialized'); 11586/** 11587 * `PlatformLocation` encapsulates all of the direct calls to platform APIs. 11588 * This class should not be used directly by an application developer. Instead, use 11589 * {@link Location}. 11590 */ 11591 11592class BrowserPlatformLocation extends PlatformLocation { 11593 constructor(_doc) { 11594 super(); 11595 this._doc = _doc; 11596 11597 this._init(); 11598 } // This is moved to its own method so that `MockPlatformLocationStrategy` can overwrite it 11599 11600 /** @internal */ 11601 11602 11603 _init() { 11604 this.location = window.location; 11605 this._history = window.history; 11606 } 11607 11608 getBaseHrefFromDOM() { 11609 return getDOM().getBaseHref(this._doc); 11610 } 11611 11612 onPopState(fn) { 11613 const window = getDOM().getGlobalEventTarget(this._doc, 'window'); 11614 window.addEventListener('popstate', fn, false); 11615 return () => window.removeEventListener('popstate', fn); 11616 } 11617 11618 onHashChange(fn) { 11619 const window = getDOM().getGlobalEventTarget(this._doc, 'window'); 11620 window.addEventListener('hashchange', fn, false); 11621 return () => window.removeEventListener('hashchange', fn); 11622 } 11623 11624 get href() { 11625 return this.location.href; 11626 } 11627 11628 get protocol() { 11629 return this.location.protocol; 11630 } 11631 11632 get hostname() { 11633 return this.location.hostname; 11634 } 11635 11636 get port() { 11637 return this.location.port; 11638 } 11639 11640 get pathname() { 11641 return this.location.pathname; 11642 } 11643 11644 get search() { 11645 return this.location.search; 11646 } 11647 11648 get hash() { 11649 return this.location.hash; 11650 } 11651 11652 set pathname(newPath) { 11653 this.location.pathname = newPath; 11654 } 11655 11656 pushState(state, title, url) { 11657 if (supportsState()) { 11658 this._history.pushState(state, title, url); 11659 } else { 11660 this.location.hash = url; 11661 } 11662 } 11663 11664 replaceState(state, title, url) { 11665 if (supportsState()) { 11666 this._history.replaceState(state, title, url); 11667 } else { 11668 this.location.hash = url; 11669 } 11670 } 11671 11672 forward() { 11673 this._history.forward(); 11674 } 11675 11676 back() { 11677 this._history.back(); 11678 } 11679 11680 historyGo(relativePosition = 0) { 11681 this._history.go(relativePosition); 11682 } 11683 11684 getState() { 11685 return this._history.state; 11686 } 11687 11688} 11689 11690BrowserPlatformLocation.ɵfac = function BrowserPlatformLocation_Factory(t) { 11691 return new (t || BrowserPlatformLocation)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](DOCUMENT)); 11692}; 11693 11694BrowserPlatformLocation.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 11695 token: BrowserPlatformLocation, 11696 factory: function () { 11697 return createBrowserPlatformLocation(); 11698 }, 11699 providedIn: 'platform' 11700}); 11701 11702(function () { 11703 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](BrowserPlatformLocation, [{ 11704 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 11705 args: [{ 11706 providedIn: 'platform', 11707 // See #23917 11708 useFactory: createBrowserPlatformLocation 11709 }] 11710 }], function () { 11711 return [{ 11712 type: undefined, 11713 decorators: [{ 11714 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 11715 args: [DOCUMENT] 11716 }] 11717 }]; 11718 }, null); 11719})(); 11720 11721function supportsState() { 11722 return !!window.history.pushState; 11723} 11724 11725function createBrowserPlatformLocation() { 11726 return new BrowserPlatformLocation((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(DOCUMENT)); 11727} 11728/** 11729 * @license 11730 * Copyright Google LLC All Rights Reserved. 11731 * 11732 * Use of this source code is governed by an MIT-style license that can be 11733 * found in the LICENSE file at https://angular.io/license 11734 */ 11735 11736/** 11737 * @license 11738 * Copyright Google LLC All Rights Reserved. 11739 * 11740 * Use of this source code is governed by an MIT-style license that can be 11741 * found in the LICENSE file at https://angular.io/license 11742 */ 11743 11744/** 11745 * Joins two parts of a URL with a slash if needed. 11746 * 11747 * @param start URL string 11748 * @param end URL string 11749 * 11750 * 11751 * @returns The joined URL string. 11752 */ 11753 11754 11755function joinWithSlash(start, end) { 11756 if (start.length == 0) { 11757 return end; 11758 } 11759 11760 if (end.length == 0) { 11761 return start; 11762 } 11763 11764 let slashes = 0; 11765 11766 if (start.endsWith('/')) { 11767 slashes++; 11768 } 11769 11770 if (end.startsWith('/')) { 11771 slashes++; 11772 } 11773 11774 if (slashes == 2) { 11775 return start + end.substring(1); 11776 } 11777 11778 if (slashes == 1) { 11779 return start + end; 11780 } 11781 11782 return start + '/' + end; 11783} 11784/** 11785 * Removes a trailing slash from a URL string if needed. 11786 * Looks for the first occurrence of either `#`, `?`, or the end of the 11787 * line as `/` characters and removes the trailing slash if one exists. 11788 * 11789 * @param url URL string. 11790 * 11791 * @returns The URL string, modified if needed. 11792 */ 11793 11794 11795function stripTrailingSlash(url) { 11796 const match = url.match(/#|\?|$/); 11797 const pathEndIdx = match && match.index || url.length; 11798 const droppedSlashIdx = pathEndIdx - (url[pathEndIdx - 1] === '/' ? 1 : 0); 11799 return url.slice(0, droppedSlashIdx) + url.slice(pathEndIdx); 11800} 11801/** 11802 * Normalizes URL parameters by prepending with `?` if needed. 11803 * 11804 * @param params String of URL parameters. 11805 * 11806 * @returns The normalized URL parameters string. 11807 */ 11808 11809 11810function normalizeQueryParams(params) { 11811 return params && params[0] !== '?' ? '?' + params : params; 11812} 11813/** 11814 * @license 11815 * Copyright Google LLC All Rights Reserved. 11816 * 11817 * Use of this source code is governed by an MIT-style license that can be 11818 * found in the LICENSE file at https://angular.io/license 11819 */ 11820 11821/** 11822 * Enables the `Location` service to read route state from the browser's URL. 11823 * Angular provides two strategies: 11824 * `HashLocationStrategy` and `PathLocationStrategy`. 11825 * 11826 * Applications should use the `Router` or `Location` services to 11827 * interact with application route state. 11828 * 11829 * For instance, `HashLocationStrategy` produces URLs like 11830 * <code class="no-auto-link">http://example.com#/foo</code>, 11831 * and `PathLocationStrategy` produces 11832 * <code class="no-auto-link">http://example.com/foo</code> as an equivalent URL. 11833 * 11834 * See these two classes for more. 11835 * 11836 * @publicApi 11837 */ 11838 11839 11840class LocationStrategy { 11841 historyGo(relativePosition) { 11842 throw new Error('Not implemented'); 11843 } 11844 11845} 11846 11847LocationStrategy.ɵfac = function LocationStrategy_Factory(t) { 11848 return new (t || LocationStrategy)(); 11849}; 11850 11851LocationStrategy.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 11852 token: LocationStrategy, 11853 factory: function () { 11854 return (() => (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(PathLocationStrategy))(); 11855 }, 11856 providedIn: 'root' 11857}); 11858 11859(function () { 11860 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](LocationStrategy, [{ 11861 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 11862 args: [{ 11863 providedIn: 'root', 11864 useFactory: () => (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(PathLocationStrategy) 11865 }] 11866 }], null, null); 11867})(); 11868/** 11869 * A predefined [DI token](guide/glossary#di-token) for the base href 11870 * to be used with the `PathLocationStrategy`. 11871 * The base href is the URL prefix that should be preserved when generating 11872 * and recognizing URLs. 11873 * 11874 * @usageNotes 11875 * 11876 * The following example shows how to use this token to configure the root app injector 11877 * with a base href value, so that the DI framework can supply the dependency anywhere in the app. 11878 * 11879 * ```typescript 11880 * import {Component, NgModule} from '@angular/core'; 11881 * import {APP_BASE_HREF} from '@angular/common'; 11882 * 11883 * @NgModule({ 11884 * providers: [{provide: APP_BASE_HREF, useValue: '/my/app'}] 11885 * }) 11886 * class AppModule {} 11887 * ``` 11888 * 11889 * @publicApi 11890 */ 11891 11892 11893const APP_BASE_HREF = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('appBaseHref'); 11894/** 11895 * @description 11896 * A {@link LocationStrategy} used to configure the {@link Location} service to 11897 * represent its state in the 11898 * [path](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax) of the 11899 * browser's URL. 11900 * 11901 * If you're using `PathLocationStrategy`, you may provide a {@link APP_BASE_HREF} 11902 * or add a `<base href>` element to the document to override the default. 11903 * 11904 * For instance, if you provide an `APP_BASE_HREF` of `'/my/app/'` and call 11905 * `location.go('/foo')`, the browser's URL will become 11906 * `example.com/my/app/foo`. To ensure all relative URIs resolve correctly, 11907 * the `<base href>` and/or `APP_BASE_HREF` should end with a `/`. 11908 * 11909 * Similarly, if you add `<base href='/my/app/'/>` to the document and call 11910 * `location.go('/foo')`, the browser's URL will become 11911 * `example.com/my/app/foo`. 11912 *
11913 * Note that when using `PathLocationStrategy`, neither the query nor 11914 * the fragment in the `<base href>` will be preserved, as outlined 11915 * by the [RFC](https://tools.ietf.org/html/rfc3986#section-5.2.2). 11916 * 11917 * @usageNotes 11918 * 11919 * ### Example 11920 * 11921 * {@example common/location/ts/path_location_component.ts region='LocationComponent'} 11922 * 11923 * @publicApi 11924 */ 11925 11926class PathLocationStrategy extends LocationStrategy { 11927 constructor(_platformLocation, href) { 11928 super(); 11929 this._platformLocation = _platformLocation; 11930 this._removeListenerFns = []; 11931 this._baseHref = href ?? this._platformLocation.getBaseHrefFromDOM() ?? (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(DOCUMENT).location?.origin ?? ''; 11932 } 11933 /** @nodoc */ 11934 11935 11936 ngOnDestroy() { 11937 while (this._removeListenerFns.length) { 11938 this._removeListenerFns.pop()(); 11939 } 11940 } 11941 11942 onPopState(fn) { 11943 this._removeListenerFns.push(this._platformLocation.onPopState(fn), this._platformLocation.onHashChange(fn)); 11944 } 11945 11946 getBaseHref() { 11947 return this._baseHref; 11948 } 11949 11950 prepareExternalUrl(internal) { 11951 return joinWithSlash(this._baseHref, internal); 11952 } 11953 11954 path(includeHash = false) { 11955 const pathname = this._platformLocation.pathname + normalizeQueryParams(this._platformLocation.search); 11956 const hash = this._platformLocation.hash; 11957 return hash && includeHash ? `${pathname}${hash}` : pathname; 11958 } 11959 11960 pushState(state, title, url, queryParams) { 11961 const externalUrl = this.prepareExternalUrl(url + normalizeQueryParams(queryParams)); 11962 11963 this._platformLocation.pushState(state, title, externalUrl); 11964 } 11965 11966 replaceState(state, title, url, queryParams) { 11967 const externalUrl = this.prepareExternalUrl(url + normalizeQueryParams(queryParams)); 11968 11969 this._platformLocation.replaceState(state, title, externalUrl); 11970 } 11971 11972 forward() { 11973 this._platformLocation.forward(); 11974 } 11975 11976 back() { 11977 this._platformLocation.back(); 11978 } 11979 11980 getState() { 11981 return this._platformLocation.getState(); 11982 } 11983 11984 historyGo(relativePosition = 0) { 11985 this._platformLocation.historyGo?.(relativePosition); 11986 } 11987 11988} 11989 11990PathLocationStrategy.ɵfac = function PathLocationStrategy_Factory(t) { 11991 return new (t || PathLocationStrategy)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](PlatformLocation), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](APP_BASE_HREF, 8)); 11992}; 11993 11994PathLocationStrategy.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 11995 token: PathLocationStrategy, 11996 factory: PathLocationStrategy.ɵfac, 11997 providedIn: 'root' 11998}); 11999 12000(function () { 12001 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](PathLocationStrategy, [{ 12002 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 12003 args: [{ 12004 providedIn: 'root' 12005 }] 12006 }], function () { 12007 return [{ 12008 type: PlatformLocation 12009 }, { 12010 type: undefined, 12011 decorators: [{ 12012 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 12013 }, { 12014 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 12015 args: [APP_BASE_HREF] 12016 }] 12017 }]; 12018 }, null); 12019})(); 12020/** 12021 * @license 12022 * Copyright Google LLC All Rights Reserved. 12023 * 12024 * Use of this source code is governed by an MIT-style license that can be 12025 * found in the LICENSE file at https://angular.io/license 12026 */ 12027 12028/** 12029 * @description 12030 * A {@link LocationStrategy} used to configure the {@link Location} service to 12031 * represent its state in the 12032 * [hash fragment](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax) 12033 * of the browser's URL. 12034 * 12035 * For instance, if you call `location.go('/foo')`, the browser's URL will become 12036 * `example.com#/foo`. 12037 * 12038 * @usageNotes 12039 * 12040 * ### Example 12041 * 12042 * {@example common/location/ts/hash_location_component.ts region='LocationComponent'} 12043 * 12044 * @publicApi 12045 */ 12046 12047 12048class HashLocationStrategy extends LocationStrategy { 12049 constructor(_platformLocation, _baseHref) { 12050 super(); 12051 this._platformLocation = _platformLocation; 12052 this._baseHref = ''; 12053 this._removeListenerFns = []; 12054 12055 if (_baseHref != null) { 12056 this._baseHref = _baseHref; 12057 } 12058 } 12059 /** @nodoc */ 12060 12061 12062 ngOnDestroy() { 12063 while (this._removeListenerFns.length) { 12064 this._removeListenerFns.pop()(); 12065 } 12066 } 12067 12068 onPopState(fn) { 12069 this._removeListenerFns.push(this._platformLocation.onPopState(fn), this._platformLocation.on
12069HashChange(fn)); 12070 } 12071 12072 getBaseHref() { 12073 return this._baseHref; 12074 } 12075 12076 path(includeHash = false) { 12077 // the hash value is always prefixed with a `#` 12078 // and if it is empty then it will stay empty 12079 let path = this._platformLocation.hash; 12080 if (path == null) path = '#'; 12081 return path.length > 0 ? path.substring(1) : path; 12082 } 12083 12084 prepareExternalUrl(internal) { 12085 const url = joinWithSlash(this._baseHref, internal); 12086 return url.length > 0 ? '#' + url : url; 12087 } 12088 12089 pushState(state, title, path, queryParams) { 12090 let url = this.prepareExternalUrl(path + normalizeQueryParams(queryParams)); 12091 12092 if (url.length == 0) { 12093 url = this._platformLocation.pathname; 12094 } 12095 12096 this._platformLocation.pushState(state, title, url); 12097 } 12098 12099 replaceState(state, title, path, queryParams) { 12100 let url = this.prepareExternalUrl(path + normalizeQueryParams(queryParams)); 12101 12102 if (url.length == 0) { 12103 url = this._platformLocation.pathname; 12104 } 12105 12106 this._platformLocation.replaceState(state, title, url); 12107 } 12108 12109 forward() { 12110 this._platformLocation.forward(); 12111 } 12112 12113 back() { 12114 this._platformLocation.back(); 12115 } 12116 12117 getState() { 12118 return this._platformLocation.getState(); 12119 } 12120 12121 historyGo(relativePosition = 0) { 12122 this._platformLocation.historyGo?.(relativePosition); 12123 } 12124 12125} 12126 12127HashLocationStrategy.ɵfac = function HashLocationStrategy_Factory(t) { 12128 return new (t || HashLocationStrategy)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](PlatformLocation), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](APP_BASE_HREF, 8)); 12129}; 12130 12131HashLocationStrategy.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 12132 token: HashLocationStrategy, 12133 factory: HashLocationStrategy.ɵfac 12134}); 12135 12136(function () { 12137 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](HashLocationStrategy, [{ 12138 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable 12139 }], function () { 12140 return [{ 12141 type: PlatformLocation 12142 }, { 12143 type: undefined, 12144 decorators: [{ 12145 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 12146 }, { 12147 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 12148 args: [APP_BASE_HREF] 12149 }] 12150 }]; 12151 }, null); 12152})(); 12153/** 12154 * @license 12155 * Copyright Google LLC All Rights Reserved. 12156 * 12157 * Use of this source code is governed by an MIT-style license that can be 12158 * found in the LICENSE file at https://angular.io/license 12159 */ 12160 12161/** 12162 * @description 12163 * 12164 * A service that applications can use to interact with a browser's URL. 12165 * 12166 * Depending on the `LocationStrategy` used, `Location` persists 12167 * to the URL's path or the URL's hash segment. 12168 * 12169 * @usageNotes 12170 * 12171 * It's better to use the `Router.navigate()` service to trigger route changes. Use 12172 * `Location` only if you need to interact with or create normalized URLs outside of 12173 * routing. 12174 * 12175 * `Location` is responsible for normalizing the URL against the application's base href. 12176 * A normalized URL is absolute from the URL host, includes the application's base href, and has no 12177 * trailing slash: 12178 * - `/my/app/user/123` is normalized 12179 * - `my/app/user/123` **is not** normalized 12180 * - `/my/app/user/123/` **is not** normalized 12181 * 12182 * ### Example 12183 * 12184 * <code-example path='common/location/ts/path_location_component.ts' 12185 * region='LocationComponent'></code-example> 12186 * 12187 * @publicApi 12188 */ 12189 12190 12191class Location { 12192 constructor(locationStrategy) { 12193 /** @internal */ 12194 this._subject = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); 12195 /** @internal */ 12196 12197 this._urlChangeListeners = []; 12198 /** @internal */ 12199 12200 this._urlChangeSubscription = null; 12201 this._locationStrategy = locationStrategy; 12202 12203 const browserBaseHref = this._locationStrategy.getBaseHref(); 12204 12205 this._baseHref = stripTrailingSlash(_stripIndexHtml(browserBaseHref)); 12206 12207 this._locationStrategy.onPopState(ev => { 12208 this._subject.emit({ 12209 'url': this.path(true), 12210 'pop': true, 12211 'state': ev.state, 12212 'type': ev.type 12213 }); 12214 }); 12215 } 12216 /** @nodoc */ 12217 12218 12219 ngOnDestroy() { 12220 this._urlChangeSubscription?.unsubscribe(); 12221 this._urlChangeListeners = []; 12222 } 12223 /** 12224 * Normalizes the URL path for this location. 12225 * 12226 * @param includeHash True to include an anchor fragment in the path.
vendor: 4,681 bytes, lines 12227-12388
12227 * 12228 * @returns The normalized URL path. 12229 */ 12230 // TODO: vsavkin. Remove the boolean flag and always include hash once the deprecated router is 12231 // removed. 12232 12233 12234 path(includeHash = false) { 12235 return this.normalize(this._locationStrategy.path(includeHash)); 12236 } 12237 /** 12238 * Reports the current state of the location history. 12239 * @returns The current value of the `history.state` object. 12240 */ 12241 12242 12243 getState() { 12244 return this._locationStrategy.getState(); 12245 } 12246 /** 12247 * Normalizes the given path and compares to the current normalized path. 12248 * 12249 * @param path The given URL path. 12250 * @param query Query parameters. 12251 * 12252 * @returns True if the given URL path is equal to the current normalized path, false 12253 * otherwise. 12254 */ 12255 12256 12257 isCurrentPathEqualTo(path, query = '') { 12258 return this.path() == this.normalize(path + normalizeQueryParams(query)); 12259 } 12260 /** 12261 * Normalizes a URL path by stripping any trailing slashes. 12262 * 12263 * @param url String representing a URL. 12264 * 12265 * @returns The normalized URL string. 12266 */ 12267 12268 12269 normalize(url) { 12270 return Location.stripTrailingSlash(_stripBaseHref(this._baseHref, _stripIndexHtml(url))); 12271 } 12272 /** 12273 * Normalizes an external URL path. 12274 * If the given URL doesn't begin with a leading slash (`'/'`), adds one 12275 * before normalizing. Adds a hash if `HashLocationStrategy` is 12276 * in use, or the `APP_BASE_HREF` if the `PathLocationStrategy` is in use. 12277 * 12278 * @param url String representing a URL. 12279 * 12280 * @returns A normalized platform-specific URL. 12281 */ 12282 12283 12284 prepareExternalUrl(url) { 12285 if (url && url[0] !== '/') { 12286 url = '/' + url; 12287 } 12288 12289 return this._locationStrategy.prepareExternalUrl(url); 12290 } // TODO: rename this method to pushState 12291 12292 /** 12293 * Changes the browser's URL to a normalized version of a given URL, and pushes a 12294 * new item onto the platform's history. 12295 * 12296 * @param path URL path to normalize. 12297 * @param query Query parameters. 12298 * @param state Location history state. 12299 * 12300 */ 12301 12302 12303 go(path, query = '', state = null) { 12304 this._locationStrategy.pushState(state, '', path, query); 12305 12306 this._notifyUrlChangeListeners(this.prepareExternalUrl(path + normalizeQueryParams(query)), state); 12307 } 12308 /** 12309 * Changes the browser's URL to a normalized version of the given URL, and replaces 12310 * the top item on the platform's history stack. 12311 * 12312 * @param path URL path to normalize. 12313 * @param query Query parameters. 12314 * @param state Location history state. 12315 */ 12316 12317 12318 replaceState(path, query = '', state = null) { 12319 this._locationStrategy.replaceState(state, '', path, query); 12320 12321 this._notifyUrlChangeListeners(this.prepareExternalUrl(path + normalizeQueryParams(query)), state); 12322 } 12323 /** 12324 * Navigates forward in the platform's history. 12325 */ 12326 12327 12328 forward() { 12329 this._locationStrategy.forward(); 12330 } 12331 /** 12332 * Navigates back in the platform's history. 12333 */ 12334 12335 12336 back() { 12337 this._locationStrategy.back(); 12338 } 12339 /** 12340 * Navigate to a specific page from session history, identified by its relative position to the 12341 * current page. 12342 * 12343 * @param relativePosition Position of the target page in the history relative to the current 12344 * page. 12345 * A negative value moves backwards, a positive value moves forwards, e.g. `location.historyGo(2)` 12346 * moves forward two pages and `location.historyGo(-2)` moves back two pages. When we try to go 12347 * beyond what's stored in the history session, we stay in the current page. Same behaviour occurs 12348 * when `relativePosition` equals 0. 12349 * @see https://developer.mozilla.org/en-US/docs/Web/API/History_API#Moving_to_a_specific_point_in_history 12350 */ 12351 12352 12353 historyGo(relativePosition = 0) { 12354 this._locationStrategy.historyGo?.(relativePosition); 12355 } 12356 /** 12357 * Registers a URL change listener. Use to catch updates performed by the Angular 12358 * framework that are not detectible through "popstate" or "hashchange" events. 12359 * 12360 * @param fn The change handler function, which take a URL and a location history state. 12361 * @returns A function that, when executed, unregisters a URL change listener. 12362 */ 12363 12364 12365 onUrlChange(fn) { 12366 this._urlChangeListeners.push(fn); 12367 12368 if (!this._urlChangeSubscription) { 12369 this._urlChangeSubscription = this.subscribe(v => { 12370 this._notifyUrlChangeListeners(v.url, v.state); 12371 }); 12372 } 12373 12374 return () => { 12375 const fnIndex = this._urlChangeListeners.indexOf(fn); 12376 12377 this._urlChangeListeners.splice(fnIndex, 1); 12378 12379 if (this._urlChangeListeners.length === 0) { 12380 this._urlChangeSubscription?.unsubscribe(); 12381 this._urlChangeSubscription = null; 12382 } 12383 }; 12384 } 12385 /** @internal */ 12386 12387 12388 _notifyUrlChangeListeners(url = '', state) {
12389 this._urlChangeListeners.forEach(fn => fn(url, state)); 12390 } 12391 /** 12392 * Subscribes to the platform's `popState` events. 12393 * 12394 * Note: `Location.go()` does not trigger the `popState` event in the browser. Use 12395 * `Location.onUrlChange()` to subscribe to URL changes instead. 12396 * 12397 * @param value Event that is triggered when the state history changes. 12398 * @param exception The exception to throw. 12399 * 12400 * @see [onpopstate](https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate) 12401 * 12402 * @returns Subscribed events. 12403 */ 12404 12405 12406 subscribe(onNext, onThrow, onReturn) { 12407 return this._subject.subscribe({ 12408 next: onNext, 12409 error: onThrow, 12410 complete: onReturn 12411 }); 12412 } 12413 12414} 12415/** 12416 * Normalizes URL parameters by prepending with `?` if needed. 12417 * 12418 * @param params String of URL parameters. 12419 * 12420 * @returns The normalized URL parameters string. 12421 */ 12422 12423 12424Location.normalizeQueryParams = normalizeQueryParams; 12425/** 12426 * Joins two parts of a URL with a slash if needed. 12427 * 12428 * @param start URL string 12429 * @param end URL string 12430 * 12431 * 12432 * @returns The joined URL string. 12433 */ 12434 12435Location.joinWithSlash = joinWithSlash; 12436/** 12437 * Removes a trailing slash from a URL string if needed. 12438 * Looks for the first occurrence of either `#`, `?`, or the end of the 12439 * line as `/` characters and removes the trailing slash if one exists. 12440 * 12441 * @param url URL string. 12442 * 12443 * @returns The URL string, modified if needed. 12444 */ 12445 12446Location.stripTrailingSlash = stripTrailingSlash; 12447 12448Location.ɵfac = function Location_Factory(t) { 12449 return new (t || Location)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](LocationStrategy)); 12450}; 12451 12452Location.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 12453 token: Location, 12454 factory: function () { 12455 return createLocation(); 12456 }, 12457 providedIn: 'root' 12458}); 12459 12460(function () { 12461 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](Location, [{ 12462 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 12463 args: [{ 12464 providedIn: 'root', 12465 // See #23917 12466 useFactory: createLocation 12467 }] 12468 }], function () { 12469 return [{ 12470 type: LocationStrategy 12471 }]; 12472 }, null); 12473})(); 12474 12475function createLocation() { 12476 return new Location((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(LocationStrategy)); 12477} 12478 12479function _stripBaseHref(baseHref, url) { 12480 return baseHref && url.startsWith(baseHref) ? url.substring(baseHref.length) : url; 12481} 12482 12483function _stripIndexHtml(url) { 12484 return url.replace(/\/index.html$/, ''); 12485} 12486/** 12487 * @license 12488 * Copyright Google LLC All Rights Reserved. 12489 * 12490 * Use of this source code is governed by an MIT-style license that can be 12491 * found in the LICENSE file at https://angular.io/license 12492 */ 12493 12494/** 12495 * @license 12496 * Copyright Google LLC All Rights Reserved. 12497 * 12498 * Use of this source code is governed by an MIT-style license that can be 12499 * found in the LICENSE file at https://angular.io/license 12500 */ 12501 12502/** @internal */ 12503 12504 12505const CURRENCIES_EN = { 12506 "ADP": [undefined, undefined, 0], 12507 "AFN": [undefined, "Ø", 0], 12508 "ALL": [undefined, undefined, 0], 12509 "AMD": [undefined, "Ö", 2], 12510 "AOA": [undefined, "Kz"], 12511 "ARS": [undefined, "$"], 12512 "AUD": ["A$", "$"], 12513 "AZN": [undefined, "â¼"], 12514 "BAM": [undefined, "KM"], 12515 "BBD": [undefined, "$"], 12516 "BDT": [undefined, "à§³"], 12517 "BHD": [undefined, undefined, 3], 12518 "BIF": [undefined, undefined, 0], 12519 "BMD": [undefined, "$"], 12520 "BND": [undefined, "$"], 12521 "BOB": [undefined, "Bs"], 12522 "BRL": ["R$"], 12523 "BSD": [undefined, "$"], 12524 "BWP": [undefined, "P"], 12525 "BYN": [undefined, undefined, 2], 12526 "BYR": [undefined, undefined, 0], 12527 "BZD": [undefined, "$"], 12528 "CAD": ["CA$", "$", 2], 12529 "CHF": [undefined, undefined, 2], 12530 "CLF": [undefined, undefined, 4], 12531 "CLP": [undefined, "$", 0], 12532 "CNY": ["CNÂ¥", "Â¥"], 12533 "COP": [undefined, "$", 2], 12534 "CRC": [undefined, "â¡", 2], 12535 "CUC": [undefined, "$"], 12536 "CUP": [undefined, "$"], 12537 "CZK": [undefined, "KÄ", 2], 12538 "DJF": [undefined, undefined, 0], 12539 "DKK": [undefined, "kr", 2], 12540 "DOP": [undefined, "$"], 12541 "EGP": [undefined, "E£"], 12542 "ESP": [undefined, "â§", 0], 12543 "EUR": ["â¬"], 12544 "FJD": [undefined, "$"], 12545 "FKP": [undefined, "£"], 12546 "GBP": ["£"], 12547 "GEL": [undefined, "â¾"], 12548 "GHS": [undefined, "GHâµ"], 12549 "GIP": [undefined, "£"], 12550 "GNF": [undefined, "FG", 0], 12551 "GTQ": [undefined, "Q"], 12552 "GYD": [undefined, "$", 2], 12553 "HKD": ["HK$", "$"], 12554 "HNL": [undefined, "L"], 12555 "HRK": [undefined, "kn"], 12556 "HUF": [undefined, "Ft", 2], 12557 "IDR": [undefined, "Rp", 2], 12558 "ILS": ["âª"], 12559 "INR": ["â¹"], 12560 "IQD": [undefined, undefined, 0], 12561 "IRR": [undefined, undefined, 0], 12562 "ISK": [undefined, "kr", 0], 12563 "ITL": [undefined, undefined, 0], 12564 "JMD": [undefined, "$"], 12565 "JOD": [undefined, undefined, 3], 12566 "JPY": ["Â¥", undefined, 0], 12567 "KHR": [undefined, "á"], 12568 "KMF": [undefined, "CF", 0], 12569 "KPW": [undefined, "â©", 0], 12570 "KRW": ["â©", undefined, 0], 12571 "KWD": [undefined, undefined, 3], 12572 "KYD": [undefined, "$"], 12573 "KZT": [undefined, "â¸"], 12574 "LAK": [undefined, "â", 0], 12575 "LBP": [undefined, "L£", 0], 12576 "LKR": [undefined, "Rs"], 12577 "LRD": [undefined, "$"], 12578 "LTL": [undefined, "Lt"], 12579 "LUF": [undefined, undefined, 0], 12580 "LVL": [undefined, "Ls"], 12581 "LYD": [undefined, undefined, 3], 12582 "MGA": [undefined, "Ar", 0], 12583 "MGF": [undefined, undefined, 0], 12584 "MMK": [undefined, "K", 0], 12585 "MNT": [undefined, "â®", 2], 12586 "MRO": [undefined, undefined, 0], 12587 "MUR": [undefined, "Rs", 2], 12588 "MXN": ["MX$", "$"], 12589 "MYR": [undefined, "RM"], 12590 "NAD": [undefined, "$"], 12591 "NGN": [undefined, "â¦"], 12592 "NIO": [undefined, "C$"], 12593 "NOK": [undefined, "kr", 2], 12594 "NPR": [undefined, "Rs"], 12595 "NZD": ["NZ$", "$"], 12596 "OMR": [undefined, undefined, 3], 12597 "PHP": ["â±"], 12598 "PKR": [undefined, "Rs", 2], 12599 "PLN": [undefined, "zÅ"], 12600 "PYG": [undefined, "â²", 0], 12601 "RON": [undefined, "lei"], 12602 "RSD": [undefined, undefined, 0], 12603 "RUB": [undefined, "â½"], 12604 "RWF": [undefined, "RF", 0], 12605 "SBD": [undefined, "$"], 12606 "SEK": [undefined, "kr", 2], 12607 "SGD": [undefined, "$"], 12608 "SHP": [undefined, "£"], 12609 "SLE": [undefined, undefined, 2], 12610 "SLL": [undefined, undefined, 0], 12611 "SOS": [undefined, undefined, 0], 12612 "SRD": [undefined, "$"], 12613 "SSP": [undefined, "£"], 12614 "STD": [undefined, undefined, 0], 12615 "STN": [undefined, "Db"], 12616 "SYP": [undefined, "£", 0], 12617 "THB": [undefined, "฿"], 12618 "TMM": [undefined, undefined, 0], 12619 "TND": [undefined, undefined, 3], 12620 "TOP": [undefined, "T$"], 12621 "TRL": [undefined, undefined, 0], 12622 "TRY": [undefined, "âº"], 12623 "TTD": [undefined, "$"], 12624 "TWD": ["NT$", "$", 2], 12625 "TZS": [undefined, undefined, 2], 12626 "UAH": [undefined, "â´"], 12627 "UGX": [undefined, undefined, 0], 12628 "USD": ["$"], 12629 "UYI": [undefined, undefined, 0], 12630 "UYU": [undefined, "$"], 12631 "UYW": [undefined, undefined, 4], 12632 "UZS": [undefined, undefined, 2], 12633 "VEF": [undefined, "Bs", 2], 12634 "VND": ["â«", undefined, 0], 12635 "VUV": [undefined, undefined, 0], 12636 "XAF": ["FCFA", undefined, 0], 12637 "XCD": ["EC$", "$"], 12638 "XOF": ["Fâ¯CFA", undefined, 0], 12639 "XPF": ["CFPF", undefined, 0], 12640 "XXX": ["¤"], 12641 "YER": [undefined, undefined, 0], 12642 "ZAR": [undefined, "R"], 12643 "ZMK": [undefined, undefined, 0], 12644 "ZMW": [undefined, "ZK"], 12645 "ZWD": [undefined, undefined, 0] 12646}; 12647/** 12648 * @license 12649 * Copyright Google LLC All Rights Reserved. 12650 * 12651 * Use of this source code is governed by an MIT-style license that can be 12652 * found in the LICENSE file at https://angular.io/license 12653 */ 12654 12655/** 12656 * Format styles that can be used to represent numbers.
12657 * @see `getLocaleNumberFormat()`. 12658 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 12659 * 12660 * @publicApi 12661 */ 12662 12663var NumberFormatStyle; 12664 12665(function (NumberFormatStyle) { 12666 NumberFormatStyle[NumberFormatStyle["Decimal"] = 0] = "Decimal"; 12667 NumberFormatStyle[NumberFormatStyle["Percent"] = 1] = "Percent"; 12668 NumberFormatStyle[NumberFormatStyle["Currency"] = 2] = "Currency"; 12669 NumberFormatStyle[NumberFormatStyle["Scientific"] = 3] = "Scientific"; 12670})(NumberFormatStyle || (NumberFormatStyle = {})); 12671/** 12672 * Plurality cases used for translating plurals to different languages. 12673 * 12674 * @see `NgPlural` 12675 * @see `NgPluralCase` 12676 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 12677 * 12678 * @publicApi 12679 */ 12680 12681 12682var Plural; 12683 12684(function (Plural) { 12685 Plural[Plural["Zero"] = 0] = "Zero"; 12686 Plural[Plural["One"] = 1] = "One"; 12687 Plural[Plural["Two"] = 2] = "Two"; 12688 Plural[Plural["Few"] = 3] = "Few"; 12689 Plural[Plural["Many"] = 4] = "Many"; 12690 Plural[Plural["Other"] = 5] = "Other"; 12691})(Plural || (Plural = {})); 12692/** 12693 * Context-dependant translation forms for strings. 12694 * Typically the standalone version is for the nominative form of the word, 12695 * and the format version is used for the genitive case. 12696 * @see [CLDR website](http://cldr.unicode.org/translation/date-time-1/date-time#TOC-Standalone-vs.-Format-Styles) 12697 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 12698 * 12699 * @publicApi 12700 */ 12701 12702 12703var FormStyle; 12704 12705(function (FormStyle) { 12706 FormStyle[FormStyle["Format"] = 0] = "Format"; 12707 FormStyle[FormStyle["Standalone"] = 1] = "Standalone"; 12708})(FormStyle || (FormStyle = {})); 12709/** 12710 * String widths available for translations. 12711 * The specific character widths are locale-specific. 12712 * Examples are given for the word "Sunday" in English. 12713 * 12714 * @publicApi 12715 */ 12716 12717 12718var TranslationWidth; 12719 12720(function (TranslationWidth) { 12721 /** 1 character for `en-US`. For example: 'S' */ 12722 TranslationWidth[TranslationWidth["Narrow"] = 0] = "Narrow"; 12723 /** 3 characters for `en-US`. For example: 'Sun' */ 12724 12725 TranslationWidth[TranslationWidth["Abbreviated"] = 1] = "Abbreviated"; 12726 /** Full length for `en-US`. For example: "Sunday" */ 12727 12728 TranslationWidth[TranslationWidth["Wide"] = 2] = "Wide"; 12729 /** 2 characters for `en-US`, For example: "Su" */ 12730 12731 TranslationWidth[TranslationWidth["Short"] = 3] = "Short"; 12732})(TranslationWidth || (TranslationWidth = {})); 12733/** 12734 * String widths available for date-time formats. 12735 * The specific character widths are locale-specific. 12736 * Examples are given for `en-US`. 12737 * 12738 * @see `getLocaleDateFormat()` 12739 * @see `getLocaleTimeFormat()` 12740 * @see `getLocaleDateTimeFormat()` 12741 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 12742 * @publicApi 12743 */ 12744 12745 12746var FormatWidth; 12747 12748(function (FormatWidth) { 12749 /** 12750 * For `en-US`, 'M/d/yy, h:mm a'` 12751 * (Example: `6/15/15, 9:03 AM`) 12752 */ 12753 FormatWidth[FormatWidth["Short"] = 0] = "Short"; 12754 /** 12755 * For `en-US`, `'MMM d, y, h:mm:ss a'` 12756 * (Example: `Jun 15, 2015, 9:03:01 AM`) 12757 */ 12758 12759 FormatWidth[FormatWidth["Medium"] = 1] = "Medium"; 12760 /** 12761 * For `en-US`, `'MMMM d, y, h:mm:ss a z'` 12762 * (Example: `June 15, 2015 at 9:03:01 AM GMT+1`) 12763 */ 12764 12765 FormatWidth[FormatWidth["Long"] = 2] = "Long"; 12766 /** 12767 * For `en-US`, `'EEEE, MMMM d, y, h:mm:ss a zzzz'` 12768 * (Example: `Monday, June 15, 2015 at 9:03:01 AM GMT+01:00`) 12769 */ 12770 12771 FormatWidth[FormatWidth["Full"] = 3] = "Full"; 12772})(FormatWidth || (FormatWidth = {})); 12773/** 12774 * Symbols that can be used to replace placeholders in number patterns. 12775 * Examples are based on `en-US` values. 12776 * 12777 * @see `getLocaleNumberSymbol()` 12778 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 12779 * 12780 * @publicApi 12781 */ 12782 12783 12784var NumberSymbol; 12785 12786(function (NumberSymbol) { 12787 /** 12788 * Decimal separator. 12789 * For `en-US`, the dot character. 12790 * Example: 2,345`.`67 12791 */ 12792 NumberSymbol[NumberSymbol["Decimal"] = 0] = "Decimal"; 12793 /** 12794 * Grouping separator, typically for thousands. 12795 * For `en-US`, the comma character. 12796 * Example: 2`,`345.67 12797 */ 12798 12799 NumberSymbol[NumberSymbol["Group"] = 1] = "Group"; 12800 /** 12801 * List-item separator. 12802 * Example: "one, two, and three" 12803 */ 12804 12805 NumberSymbol[NumberSymbol["List"] = 2] = "List"; 12806 /** 12807 * Sign for percentage (out of 100). 12808 * Example: 23.4% 12809 */ 12810 12811 NumberSymbol[NumberSymbol["PercentSign"] = 3] = "PercentSign"; 12812 /** 12813 * Sign for positive numbers. 12814 * Example: +23 12815 */ 12816 12817 NumberSymbol[NumberSymbol["PlusSign"] = 4] = "PlusSign"; 12818 /** 12819 * Sign for negative numbers. 12820 * Example: -23 12821 */ 12822 12823 NumberSymbol[NumberSymbol["MinusSign"] = 5] = "MinusSign"; 12824 /** 12825 * Computer notation for exponential value (n times a power of 10). 12826 * Example: 1.2E3 12827 */ 12828 12829 NumberSymbol[NumberSymbol["Exponential"] = 6] = "Exponential"; 12830 /** 12831 * Human-readable format of exponential. 12832 * Example: 1.2x103 12833 */ 12834 12835 NumberSymbol[NumberSymbol["SuperscriptingExponent"] = 7] = "SuperscriptingExponent"; 12836 /** 12837 * Sign for permille (out of 1000). 12838 * Example: 23.4â° 12839 */ 12840 12841 NumberSymbol[NumberSymbol["PerMille"] = 8] = "PerMille"; 12842 /** 12843 * Infinity, can be used with plus and minus. 12844 * Example: â, +â, -â 12845 */ 12846 12847 NumberSymbol[NumberSymbol["Infinity"] = 9] = "Infinity"; 12848 /** 12849 * Not a number. 12850 * Example: NaN 12851 */ 12852 12853 NumberSymbol[NumberSymbol["NaN"] = 10] = "NaN"; 12854 /** 12855 * Symbol used between time units. 12856 * Example: 10:52 12857 */ 12858 12859 NumberSymbol[NumberSymbol["TimeSeparator"] = 11] = "TimeSeparator"; 12860 /** 12861 * Decimal separator for currency values (fallback to `Decimal`). 12862 * Example: $2,345.67 12863 */ 12864 12865 NumberSymbol[NumberSymbol["CurrencyDecimal"] = 12] = "CurrencyDecimal"; 12866 /** 12867 * Group separator for currency values (fallback to `Group`). 12868 * Example: $2,345.67 12869 */ 12870 12871 NumberSymbol[NumberSymbol["CurrencyGroup"] = 13] = "CurrencyGroup"; 12872})(NumberSymbol || (NumberSymbol = {})); 12873/** 12874 * The value for each day of the week, based on the `en-US` locale 12875 * 12876 * @publicApi 12877 */ 12878 12879 12880var WeekDay; 12881 12882(function (WeekDay) { 12883 WeekDay[WeekDay["Sunday"] = 0] = "Sunday"; 12884 WeekDay[WeekDay["Monday"] = 1] = "Monday"; 12885 WeekDay[WeekDay["Tuesday"] = 2] = "Tuesday"; 12886 WeekDay[WeekDay["Wednesday"] = 3] = "Wednesday"; 12887 WeekDay[WeekDay["Thursday"] = 4] = "Thursday"; 12888 WeekDay[WeekDay["Friday"] = 5] = "Friday"; 12889 WeekDay[WeekDay["Saturday"] = 6] = "Saturday"; 12890})(WeekDay || (WeekDay = {})); 12891/** 12892 * Retrieves the locale ID from the currently loaded locale. 12893 * The loaded locale could be, for example, a global one rather than a regional one. 12894 * @param locale A locale code, such as `fr-FR`. 12895 * @returns The locale code. For example, `fr`. 12896 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 12897 * 12898 * @publicApi 12899 */ 12900 12901 12902function getLocaleId(locale) { 12903 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale)[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].LocaleId]; 12904} 12905/** 12906 * Retrieves day period strings for the given locale. 12907 * 12908 * @param locale A locale code for the locale format rules to use. 12909 * @param formStyle The required grammatical form. 12910 * @param width The required character width. 12911 * @returns An array of localized period strings. For example, `[AM, PM]` for `en-US`. 12912 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 12913 * 12914 * @publicApi 12915 */ 12916 12917 12918function getLocaleDayPeriods(locale, formStyle, width) { 12919 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 12920 const amPmData = [data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DayPeriodsFormat], data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DayPeriodsStandalone]]; 12921 const amPm = getLastDefinedValue(amPmData, formStyle); 12922 return getLastDefinedValue(amPm, width); 12923} 12924/** 12925 * Retrieves days of the week for the given locale, using the Gregorian calendar. 12926 * 12927 * @param locale A locale code for the locale format rules to use. 12928 * @param formStyle The required grammatical form. 12929 * @param width The required character width. 12930 * @returns An array of localized name strings. 12931 * For example,`[Sunday, Monday, ... Saturday]` for `en-US`. 12932 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 12933 * 12934 * @publicApi 12935 */ 12936 12937 12938function getLocaleDayNames(locale, formStyle, width) { 12939 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 12940 const daysData = [data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DaysFormat], data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DaysStandalone]]; 12941 const days = getLastDefinedValue(daysData, formStyle); 12942 return getLastDefinedValue(days, width); 12943} 12944/** 12945 * Retrieves months of the year for the given locale, using the Gregorian calendar. 12946 * 12947 * @param locale A locale code for the locale format rules to use. 12948 * @param formStyle The required grammatical form. 12949 * @param width The required character width. 12950 * @returns An array of localized name strings. 12951 * For example, `[January, February, ...]` for `en-US`. 12952 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 12953 * 12954 * @publicApi 12955 */ 12956 12957 12958function getLocaleMonthNames(locale, formStyle, width) { 12959 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 12960 const monthsData = [data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].MonthsFormat], data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].MonthsStandalone]]; 12961 const months = getLastDefinedValue(monthsData, formStyle); 12962 return getLastDefinedValue(months, width); 12963} 12964/** 12965 * Retrieves Gregorian-calendar eras for the given locale. 12966 * @param locale A locale code for the locale format rules to use. 12967 * @param width The required character width. 12968 12969 * @returns An array of localized era strings. 12970 * For example, `[AD, BC]` for `en-US`. 12971 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 12972 * 12973 * @publicApi 12974 */ 12975 12976 12977function getLocaleEraNames(locale, width) { 12978 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 12979 const erasData = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].Eras]; 12980 return getLastDefinedValue(erasData, width); 12981} 12982/** 12983 * Retrieves the first day of the week for the given locale. 12984 * 12985 * @param locale A locale code for the locale format rules to use. 12986 * @returns A day index number, using the 0-based week-day index for `en-US` 12987 * (Sunday = 0, Monday = 1, ...). 12988 * For example, for `fr-FR`, returns 1 to indicate that the first day is Monday. 12989 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 12990 * 12991 * @publicApi 12992 */ 12993 12994 12995function getLocaleFirstDayOfWeek(locale) { 12996 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 12997 return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].FirstDayOfWeek]; 12998} 12999/** 13000 * Range of week days that are considered the week-end for the given locale. 13001 * 13002 * @param locale A locale code for the locale format rules to use. 13003 * @returns The range of day values, `[startDay, endDay]`. 13004 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13005 * 13006 * @publicApi 13007 */ 13008 13009 13010function getLocaleWeekEndRange(locale) { 13011 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 13012 return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].WeekendRange]; 13013} 13014/** 13015 * Retrieves a localized date-value formatting string. 13016 * 13017 * @param locale A locale code for the locale format rules to use. 13018 * @param width The format type. 13019 * @returns The localized formatting string. 13020 * @see `FormatWidth` 13021 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13022 * 13023 * @publicApi 13024 */ 13025 13026 13027function getLocaleDateFormat(locale, width) { 13028 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 13029 return getLastDefinedValue(data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DateFormat], width); 13030} 13031/** 13032 * Retrieves a localized time-value formatting string. 13033 * 13034 * @param locale A locale code for the locale format rules to use. 13035 * @param width The format type. 13036 * @returns The localized formatting string. 13037 * @see `FormatWidth` 13038 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13039 13040 * @publicApi 13041 */ 13042 13043 13044function getLocaleTimeFormat(locale, width) { 13045 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 13046 return getLastDefinedValue(data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].TimeFormat], width); 13047} 13048/** 13049 * Retrieves a localized date-time formatting string. 13050 * 13051 * @param locale A locale code for the locale format rules to use. 13052 * @param width The format type. 13053 * @returns The localized formatting string. 13054 * @see `FormatWidth` 13055 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13056 * 13057 * @publicApi 13058 */ 13059 13060 13061function getLocaleDateTimeFormat(locale, width) { 13062 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 13063 const dateTimeFormatData = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DateTimeFormat]; 13064 return getLastDefinedValue(dateTimeFormatData, width); 13065} 13066/** 13067 * Retrieves a localized number symbol that can be used to replace placeholders in number formats. 13068 * @param locale The locale code. 13069 * @param symbol The symbol to localize. 13070 * @returns The character for the localized symbol. 13071 * @see `NumberSymbol` 13072 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13073 * 13074 * @publicApi 13075 */ 13076 13077 13078function getLocaleNumberSymbol(locale, symbol) { 13079 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 13080 const res = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberSymbols][symbol]; 13081 13082 if (typeof res === 'undefined') { 13083 if (symbol === NumberSymbol.CurrencyDecimal) { 13084 return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberSymbols][NumberSymbol.Decimal]; 13085 } else if (symbol === NumberSymbol.CurrencyGroup) { 13086 return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberSymbols][NumberSymbol.Group]; 13087 } 13088 } 13089 13090 return res; 13091} 13092/** 13093 * Retrieves a number format for a given locale. 13094 * 13095 * Numbers are formatted using patterns, like `#,###.00`. For example, the pattern `#,###.00`
13096 * when used to format the number 12345.678 could result in "12'345,678". That would happen if the 13097 * grouping separator for your language is an apostrophe, and the decimal separator is a comma. 13098 * 13099 * <b>Important:</b> The characters `.` `,` `0` `#` (and others below) are special placeholders 13100 * that stand for the decimal separator, and so on, and are NOT real characters. 13101 * You must NOT "translate" the placeholders. For example, don't change `.` to `,` even though in 13102 * your language the decimal point is written with a comma. The symbols should be replaced by the 13103 * local equivalents, using the appropriate `NumberSymbol` for your language. 13104 * 13105 * Here are the special characters used in number patterns: 13106 * 13107 * | Symbol | Meaning | 13108 * |--------|---------| 13109 * | . | Replaced automatically by the character used for the decimal point. | 13110 * | , | Replaced by the "grouping" (thousands) separator. | 13111 * | 0 | Replaced by a digit (or zero if there aren't enough digits). | 13112 * | # | Replaced by a digit (or nothing if there aren't enough). | 13113 * | ¤ | Replaced by a currency symbol, such as $ or USD. | 13114 * | % | Marks a percent format. The % symbol may change position, but must be retained. | 13115 * | E | Marks a scientific format. The E symbol may change position, but must be retained. | 13116 * | ' | Special characters used as literal characters are quoted with ASCII single quotes. | 13117 * 13118 * @param locale A locale code for the locale format rules to use. 13119 * @param type The type of numeric value to be formatted (such as `Decimal` or `Currency`.) 13120 * @returns The localized format string. 13121 * @see `NumberFormatStyle` 13122 * @see [CLDR website](http://cldr.unicode.org/translation/number-patterns) 13123 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13124 * 13125 * @publicApi 13126 */ 13127 13128 13129function getLocaleNumberFormat(locale, type) { 13130 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 13131 return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberFormats][type]; 13132} 13133/** 13134 * Retrieves the symbol used to represent the currency for the main country 13135 * corresponding to a given locale. For example, '$' for `en-US`. 13136 * 13137 * @param locale A locale code for the locale format rules to use. 13138 * @returns The localized symbol character, 13139 * or `null` if the main country cannot be determined. 13140 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13141 * 13142 * @publicApi 13143 */ 13144 13145 13146function getLocaleCurrencySymbol(locale) { 13147 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 13148 return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].CurrencySymbol] || null; 13149} 13150/** 13151 * Retrieves the name of the currency for the main country corresponding 13152 * to a given locale. For example, 'US Dollar' for `en-US`. 13153 * @param locale A locale code for the locale format rules to use. 13154 * @returns The currency name, 13155 * or `null` if the main country cannot be determined. 13156 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13157 * 13158 * @publicApi 13159 */ 13160 13161 13162function getLocaleCurrencyName(locale) { 13163 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 13164 return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].CurrencyName] || null; 13165} 13166/** 13167 * Retrieves the default currency code for the given locale. 13168 * 13169 * The default is defined as the first currency which is still in use. 13170 * 13171 * @param locale The code of the locale whose currency code we want. 13172 * @returns The code of the default currency for the given locale. 13173 * 13174 * @publicApi 13175 */ 13176 13177 13178function getLocaleCurrencyCode(locale) { 13179 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵgetLocaleCurrencyCode"])(locale); 13180} 13181/** 13182 * Retrieves the currency values for a given locale. 13183 * @param locale A locale code for the locale format rules to use. 13184 * @returns The currency values. 13185 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13186 */ 13187 13188 13189function getLocaleCurrencies(locale) { 13190 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 13191 return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].Currencies]; 13192} 13193/** 13194 * @alias core/ɵgetLocalePluralCase 13195 * @publicApi 13196 */ 13197 13198 13199const getLocalePluralCase = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵgetLocalePluralCase"]; 13200 13201function checkFullData(data) { 13202 if (!data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData]) { 13203 throw new Error(`Missing extra locale data for the locale "${data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].LocaleId]}". Use "registerLocaleData" to load new data. See the "I18n guide" on angular.io to know more.`); 13204 } 13205} 13206/** 13207 * Retrieves locale-specific rules used to determine which day period to use 13208 * when more than one period is defined for a locale. 13209 * 13210 * There is a rule for each defined day period. The 13211 * first rule is applied to the first day period and so on. 13212 * Fall back to AM/PM when no rules are available. 13213 * 13214 * A rule can specify a period as time range, or as a single time value. 13215 * 13216 * This functionality is only available when you have loaded the full locale data. 13217 * See the ["I18n guide"](guide/i18n-common-format-data-locale). 13218 * 13219 * @param locale A locale code for the locale format rules to use. 13220 * @returns The rules for the locale, a single time value or array of *from-time, to-time*, 13221 * or null if no periods are available. 13222 * 13223 * @see `getLocaleExtraDayPeriods()` 13224 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13225 * 13226 * @publicApi 13227 */ 13228 13229 13230function getLocaleExtraDayPeriodRules(locale) { 13231 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 13232 checkFullData(data); 13233 const rules = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][2 13234 /* ɵExtraLocaleDataIndex.ExtraDayPeriodsRules */ 13235 ] || []; 13236 return rules.map(rule => { 13237 if (typeof rule === 'string') { 13238 return extractTime(rule); 13239 } 13240 13241 return [extractTime(rule[0]), extractTime(rule[1])]; 13242 }); 13243} 13244/** 13245 * Retrieves locale-specific day periods, which indicate roughly how a day is broken up 13246 * in different languages. 13247 * For example, for `en-US`, periods are morning, noon, afternoon, evening, and midnight. 13248 * 13249 * This functionality is only available when you have loaded the full locale data. 13250 * See the ["I18n guide"](guide/i18n-common-format-data-locale). 13251 * 13252 * @param locale A locale code for the locale format rules to use. 13253 * @param formStyle The required grammatical form. 13254 * @param width The required character width. 13255 * @returns The translated day-period strings. 13256 * @see `getLocaleExtraDayPeriodRules()` 13257 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13258 * 13259 * @publicApi 13260 */ 13261 13262 13263function getLocaleExtraDayPeriods(locale, formStyle, width) { 13264 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 13265 checkFullData(data); 13266 const dayPeriodsData = [data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][0 13267 /* ɵExtraLocaleDataIndex.ExtraDayPeriodFormats */ 13268 ], data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][1 13269 /* ɵExtraLocaleDataIndex.ExtraDayPeriodStandalone */ 13270 ]]; 13271 const dayPeriods = getLastDefinedValue(dayPeriodsData, formStyle) || []; 13272 return getLastDefinedValue(dayPeriods, width) || []; 13273} 13274/** 13275 * Retrieves the writing direction of a specified locale 13276 * @param locale A locale code for the locale format rules to use. 13277 * @publicApi 13278 * @returns 'rtl' or 'ltr' 13279 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13280 */ 13281 13282 13283function getLocaleDirection(locale) { 13284 const data = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); 13285 return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].Directionality]; 13286} 13287/** 13288 * Retrieves the first value that is defined in an array, going backwards from an index position. 13289 * 13290 * To avoid repeating the same data (as when the "format" and "standalone" forms are the same) 13291 * add the first value to the locale data arrays, and add other values only if they are different. 13292 * 13293 * @param data The data array to retrieve from. 13294 * @param index A 0-based index into the array to start from. 13295 * @returns The value immediately before the given index position. 13296 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13297 * 13298 * @publicApi 13299 */ 13300 13301 13302function getLastDefinedValue(data, index) { 13303 for (let i = index; i > -1; i--) { 13304 if (typeof data[i] !== 'undefined') { 13305 return data[i]; 13306 } 13307 } 13308 13309 throw new Error('Locale data API: locale data undefined'); 13310} 13311/** 13312 * Extracts the hours and minutes from a string like "15:45" 13313 */ 13314 13315 13316function extractTime(time) { 13317 const [h, m] = time.split(':'); 13318 return { 13319 hours: +h, 13320 minutes: +m 13321 }; 13322} 13323/** 13324 * Retrieves the currency symbol for a given currency code. 13325 * 13326 * For example, for the default `en-US` locale, the code `USD` can 13327 * be represented by the narrow symbol `$` or the wide symbol `US$`. 13328 * 13329 * @param code The currency code. 13330 * @param format The format, `wide` or `narrow`. 13331 * @param locale A locale code for the locale format rules to use. 13332 * 13333 * @returns The symbol, or the currency code if no symbol is available. 13334 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13335 * 13336 * @publicApi 13337 */ 13338 13339 13340function getCurrencySymbol(code, format, locale = 'en') { 13341 const currency = getLocaleCurrencies(locale)[code] || CURRENCIES_EN[code] || []; 13342 const symbolNarrow = currency[1 13343 /* ɵCurrencyIndex.SymbolNarrow */ 13344 ]; 13345 13346 if (format === 'narrow' && typeof symbolNarrow === 'string') { 13347 return symbolNarrow; 13348 } 13349 13350 return currency[0 13351 /* ɵCurrencyIndex.Symbol */ 13352 ] || code; 13353} // Most currencies have cents, that's why the default is 2 13354 13355 13356const DEFAULT_NB_OF_CURRENCY_DIGITS = 2; 13357/** 13358 * Reports the number of decimal digits for a given currency. 13359 * The value depends upon the presence of cents in that particular currency. 13360 * 13361 * @param code The currency code. 13362 * @returns The number of decimal digits, typically 0 or 2. 13363 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13364 * 13365 * @publicApi 13366 */ 13367 13368function getNumberOfCurrencyDigits(code) { 13369 let digits; 13370 const currency = CURRENCIES_EN[code]; 13371 13372 if (currency) { 13373 digits = currency[2 13374 /* ɵCurrencyIndex.NbOfDigits */ 13375 ]; 13376 } 13377 13378 return typeof digits === 'number' ? digits : DEFAULT_NB_OF_CURRENCY_DIGITS; 13379} 13380/** 13381 * @license 13382 * Copyright Google LLC All Rights Reserved. 13383 * 13384 * Use of this source code is governed by an MIT-style license that can be 13385 * found in the LICENSE file at https://angular.io/license 13386 */ 13387 13388 13389const ISO8601_DATE_REGEX = /^(\d{4,})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; // 1 2 3 4 5 6 7 8 9 10 11 13390 13391const NAMED_FORMATS = {}; 13392const DATE_FORMATS_SPLIT = /((?:[^BEGHLMOSWYZabcdhmswyz']+)|(?:'(?:[^']|'')*')|(?:G{1,5}|y{1,4}|Y{1,4}|M{1,5}|L{1,5}|w{1,2}|W{1}|d{1,2}|E{1,6}|c{1,6}|a{1,5}|b{1,5}|B{1,5}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|S{1,3}|z{1,4}|Z{1,5}|O{1,4}))([\s\S]*)/; 13393var ZoneWidth; 13394 13395(function (ZoneWidth) { 13396 ZoneWidth[ZoneWidth["Short"] = 0] = "Short"; 13397 ZoneWidth[ZoneWidth["ShortGMT"] = 1] = "ShortGMT"; 13398 ZoneWidth[ZoneWidth["Long"] = 2] = "Long"; 13399 ZoneWidth[ZoneWidth["Extended"] = 3] = "Extended"; 13400})(ZoneWidth || (ZoneWidth = {})); 13401 13402var DateType; 13403 13404(function (DateType) { 13405 DateType[DateType["FullYear"] = 0] = "FullYear"; 13406 DateType[DateType["Month"] = 1] = "Month"; 13407 DateType[DateType["Date"] = 2] = "Date"; 13408 DateType[DateType["Hours"] = 3] = "Hours"; 13409 DateType[DateType["Minutes"] = 4] = "Minutes"; 13410 DateType[DateType["Seconds"] = 5] = "Seconds"; 13411 DateType[DateType["FractionalSeconds"] = 6] = "FractionalSeconds"; 13412 DateType[DateType["Day"] = 7] = "Day"; 13413})(DateType || (DateType = {})); 13414 13415var TranslationType; 13416 13417(function (TranslationType) { 13418 TranslationType[TranslationType["DayPeriods"] = 0] = "DayPeriods"; 13419 TranslationType[TranslationType["Days"] = 1] = "Days"; 13420 TranslationType[TranslationType["Months"] = 2] = "Months"; 13421 TranslationType[TranslationType["Eras"] = 3] = "Eras"; 13422})(TranslationType || (TranslationType = {})); 13423/** 13424 * @ngModule CommonModule 13425 * @description 13426 * 13427 * Formats a date according to locale rules. 13428 * 13429 * @param value The date to format, as a Date, or a number (milliseconds since UTC epoch) 13430 * or an [ISO date-time string](https://www.w3.org/TR/NOTE-datetime). 13431 * @param format The date-time components to include. See `DatePipe` for details. 13432 * @param locale A locale code for the locale format rules to use. 13433 * @param timezone The time zone. A time zone offset from GMT (such as `'+0430'`), 13434 * or a standard UTC/GMT or continental US time zone abbreviation. 13435 * If not specified, uses host system settings. 13436 * 13437 * @returns The formatted date string. 13438 * 13439 * @see `DatePipe` 13440 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 13441 * 13442 * @publicApi 13443 */ 13444 13445 13446function formatDate(value, format, locale, timezone) { 13447 let date = toDate(value); 13448 const namedFormat = getNamedFormat(locale, format); 13449 format = namedFormat || format; 13450 let parts = []; 13451 let match; 13452 13453 while (format) { 13454 match = DATE_FORMATS_SPLIT.exec(format); 13455 13456 if (match) { 13457 parts = parts.concat(match.slice(1)); 13458 const part = parts.pop(); 13459 13460 if (!part) { 13461 break; 13462 } 13463 13464 format = part; 13465 } else { 13466 parts.push(format); 13467 break; 13468 } 13469 } 13470 13471 let dateTimezoneOffset = date.getTimezoneOffset(); 13472 13473 if (timezone) { 13474 dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset); 13475 date = convertTimezoneToLocal(date, timezone, true); 13476 } 13477 13478 let text = '';
vendor: 38,783 bytes, lines 13479-14736
13479 parts.forEach(value => { 13480 const dateFormatter = getDateFormatter(value); 13481 text += dateFormatter ? dateFormatter(date, locale, dateTimezoneOffset) : value === '\'\'' ? '\'' : value.replace(/(^'|'$)/g, '').replace(/''/g, '\''); 13482 }); 13483 return text; 13484} 13485/** 13486 * Create a new Date object with the given date value, and the time set to midnight. 13487 * 13488 * We cannot use `new Date(year, month, date)` because it maps years between 0 and 99 to 1900-1999. 13489 * See: https://github.com/angular/angular/issues/40377 13490 * 13491 * Note that this function returns a Date object whose time is midnight in the current locale's 13492 * timezone. In the future we might want to change this to be midnight in UTC, but this would be a 13493 * considerable breaking change. 13494 */ 13495 13496 13497function createDate(year, month, date) { 13498 // The `newDate` is set to midnight (UTC) on January 1st 1970. 13499 // - In PST this will be December 31st 1969 at 4pm. 13500 // - In GMT this will be January 1st 1970 at 1am. 13501 // Note that they even have different years, dates and months! 13502 const newDate = new Date(0); // `setFullYear()` allows years like 0001 to be set correctly. This function does not 13503 // change the internal time of the date. 13504 // Consider calling `setFullYear(2019, 8, 20)` (September 20, 2019). 13505 // - In PST this will now be September 20, 2019 at 4pm 13506 // - In GMT this will now be September 20, 2019 at 1am 13507 13508 newDate.setFullYear(year, month, date); // We want the final date to be at local midnight, so we reset the time. 13509 // - In PST this will now be September 20, 2019 at 12am 13510 // - In GMT this will now be September 20, 2019 at 12am 13511 13512 newDate.setHours(0, 0, 0); 13513 return newDate; 13514} 13515 13516function getNamedFormat(locale, format) { 13517 const localeId = getLocaleId(locale); 13518 NAMED_FORMATS[localeId] = NAMED_FORMATS[localeId] || {}; 13519 13520 if (NAMED_FORMATS[localeId][format]) { 13521 return NAMED_FORMATS[localeId][format]; 13522 } 13523 13524 let formatValue = ''; 13525 13526 switch (format) { 13527 case 'shortDate': 13528 formatValue = getLocaleDateFormat(locale, FormatWidth.Short); 13529 break; 13530 13531 case 'mediumDate': 13532 formatValue = getLocaleDateFormat(locale, FormatWidth.Medium); 13533 break; 13534 13535 case 'longDate': 13536 formatValue = getLocaleDateFormat(locale, FormatWidth.Long); 13537 break; 13538 13539 case 'fullDate': 13540 formatValue = getLocaleDateFormat(locale, FormatWidth.Full); 13541 break; 13542 13543 case 'shortTime': 13544 formatValue = getLocaleTimeFormat(locale, FormatWidth.Short); 13545 break; 13546 13547 case 'mediumTime': 13548 formatValue = getLocaleTimeFormat(locale, FormatWidth.Medium); 13549 break; 13550 13551 case 'longTime': 13552 formatValue = getLocaleTimeFormat(locale, FormatWidth.Long); 13553 break; 13554 13555 case 'fullTime': 13556 formatValue = getLocaleTimeFormat(locale, FormatWidth.Full); 13557 break; 13558 13559 case 'short': 13560 const shortTime = getNamedFormat(locale, 'shortTime'); 13561 const shortDate = getNamedFormat(locale, 'shortDate'); 13562 formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Short), [shortTime, shortDate]); 13563 break; 13564 13565 case 'medium': 13566 const mediumTime = getNamedFormat(locale, 'mediumTime'); 13567 const mediumDate = getNamedFormat(locale, 'mediumDate'); 13568 formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Medium), [mediumTime, mediumDate]); 13569 break; 13570 13571 case 'long': 13572 const longTime = getNamedFormat(locale, 'longTime'); 13573 const longDate = getNamedFormat(locale, 'longDate'); 13574 formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Long), [longTime, longDate]); 13575 break; 13576 13577 case 'full': 13578 const fullTime = getNamedFormat(locale, 'fullTime'); 13579 const fullDate = getNamedFormat(locale, 'fullDate'); 13580 formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Full), [fullTime, fullDate]); 13581 break; 13582 } 13583 13584 if (formatValue) { 13585 NAMED_FORMATS[localeId][format] = formatValue; 13586 } 13587 13588 return formatValue; 13589} 13590 13591function formatDateTime(str, opt_values) { 13592 if (opt_values) { 13593 str = str.replace(/\{([^}]+)}/g, function (match, key) { 13594 return opt_values != null && key in opt_values ? opt_values[key] : match; 13595 }); 13596 } 13597 13598 return str; 13599} 13600 13601function padNumber(num, digits, minusSign = '-', trim, negWrap) { 13602 let neg = ''; 13603 13604 if (num < 0 || negWrap && num <= 0) { 13605 if (negWrap) { 13606 num = -num + 1; 13607 } else { 13608 num = -num; 13609 neg = minusSign; 13610 } 13611 } 13612 13613 let strNum = String(num); 13614 13615 while (strNum.length < digits) { 13616 strNum = '0' + strNum; 13617 } 13618 13619 if (trim) { 13620 strNum = strNum.slice(strNum.length - digits); 13621 } 13622 13623 return neg + strNum; 13624} 13625 13626function formatFractionalSeconds(milliseconds, digits) { 13627 const strMs = padNumber(milliseconds, 3); 13628 return strMs.substring(0, digits); 13629} 13630/** 13631 * Returns a date formatter that transforms a date into its locale digit representation 13632 */ 13633 13634 13635function dateGetter(name, size, offset = 0, trim = false, negWrap = false) { 13636 return function (date, locale) { 13637 let part = getDatePart(name, date); 13638 13639 if (offset > 0 || part > -offset) { 13640 part += offset; 13641 } 13642 13643 if (name === DateType.Hours) { 13644 if (part === 0 && offset === -12) { 13645 part = 12; 13646 } 13647 } else if (name === DateType.FractionalSeconds) { 13648 return formatFractionalSeconds(part, size); 13649 } 13650 13651 const localeMinus = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign); 13652 return padNumber(part, size, localeMinus, trim, negWrap); 13653 }; 13654} 13655 13656function getDatePart(part, date) { 13657 switch (part) { 13658 case DateType.FullYear: 13659 return date.getFullYear(); 13660 13661 case DateType.Month: 13662 return date.getMonth(); 13663 13664 case DateType.Date: 13665 return date.getDate(); 13666 13667 case DateType.Hours: 13668 return date.getHours(); 13669 13670 case DateType.Minutes: 13671 return date.getMinutes(); 13672 13673 case DateType.Seconds: 13674 return date.getSeconds(); 13675 13676 case DateType.FractionalSeconds: 13677 return date.getMilliseconds(); 13678 13679 case DateType.Day: 13680 return date.getDay(); 13681 13682 default: 13683 throw new Error(`Unknown DateType value "${part}".`); 13684 } 13685} 13686/** 13687 * Returns a date formatter that transforms a date into its locale string representation 13688 */ 13689 13690 13691function dateStrGetter(name, width, form = FormStyle.Format, extended = false) { 13692 return function (date, locale) { 13693 return getDateTranslation(date, locale, name, width, form, extended); 13694 }; 13695} 13696/** 13697 * Returns the locale translation of a date for a given form, type and width 13698 */ 13699 13700 13701function getDateTranslation(date, locale, name, width, form, extended) { 13702 switch (name) { 13703 case TranslationType.Months: 13704 return getLocaleMonthNames(locale, form, width)[date.getMonth()]; 13705 13706 case TranslationType.Days: 13707 return getLocaleDayNames(locale, form, width)[date.getDay()]; 13708 13709 case TranslationType.DayPeriods: 13710 const currentHours = date.getHours(); 13711 const currentMinutes = date.getMinutes(); 13712 13713 if (extended) { 13714 const rules = getLocaleExtraDayPeriodRules(locale); 13715 const dayPeriods = getLocaleExtraDayPeriods(locale, form, width); 13716 const index = rules.findIndex(rule => { 13717 if (Array.isArray(rule)) { 13718 // morning, afternoon, evening, night 13719 const [from, to] = rule; 13720 const afterFrom = currentHours >= from.hours && currentMinutes >= from.minutes; 13721 const beforeTo = currentHours < to.hours || currentHours === to.hours && currentMinutes < to.minutes; // We must account for normal rules that span a period during the day (e.g. 6am-9am) 13722 // where `from` is less (earlier) than `to`. But also rules that span midnight (e.g. 13723 // 10pm - 5am) where `from` is greater (later!) than `to`. 13724 // 13725 // In the first case the current time must be BOTH after `from` AND before `to` 13726 // (e.g. 8am is after 6am AND before 10am). 13727 // 13728 // In the second case the current time must be EITHER after `from` OR before `to` 13729 // (e.g. 4am is before 5am but not after 10pm; and 11pm is not before 5am but it is 13730 // after 10pm). 13731 13732 if (from.hours < to.hours) { 13733 if (afterFrom && beforeTo) { 13734 return true; 13735 } 13736 } else if (afterFrom || beforeTo) { 13737 return true; 13738 } 13739 } else { 13740 // noon or midnight 13741 if (rule.hours === currentHours && rule.minutes === currentMinutes) { 13742 return true; 13743 } 13744 } 13745 13746 return false; 13747 }); 13748 13749 if (index !== -1) { 13750 return dayPeriods[index]; 13751 } 13752 } // if no rules for the day periods, we use am/pm by default 13753 13754 13755 return getLocaleDayPeriods(locale, form, width)[currentHours < 12 ? 0 : 1]; 13756 13757 case TranslationType.Eras: 13758 return getLocaleEraNames(locale, width)[date.getFullYear() <= 0 ? 0 : 1]; 13759 13760 default: 13761 // This default case is not needed by TypeScript compiler, as the switch is exhaustive. 13762 // However Closure Compiler does not understand that and reports an error in typed mode. 13763 // The `throw new Error` below works around the problem, and the unexpected: never variable 13764 // makes sure tsc still checks this code is unreachable. 13765 const unexpected = name; 13766 throw new Error(`unexpected translation type ${unexpected}`); 13767 } 13768} 13769/** 13770 * Returns a date formatter that transforms a date and an offset into a timezone with ISO8601 or 13771 * GMT format depending on the width (eg: short = +0430, short:GMT = GMT+4, long = GMT+04:30, 13772 * extended = +04:30) 13773 */ 13774 13775 13776function timeZoneGetter(width) { 13777 return function (date, locale, offset) { 13778 const zone = -1 * offset; 13779 const minusSign = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign); 13780 const hours = zone > 0 ? Math.floor(zone / 60) : Math.ceil(zone / 60); 13781 13782 switch (width) { 13783 case ZoneWidth.Short: 13784 return (zone >= 0 ? '+' : '') + padNumber(hours, 2, minusSign) + padNumber(Math.abs(zone % 60), 2, minusSign); 13785 13786 case ZoneWidth.ShortGMT: 13787 return 'GMT' + (zone >= 0 ? '+' : '') + padNumber(hours, 1, minusSign); 13788 13789 case ZoneWidth.Long: 13790 return 'GMT' + (zone >= 0 ? '+' : '') + padNumber(hours, 2, minusSign) + ':' + padNumber(Math.abs(zone % 60), 2, minusSign); 13791 13792 case ZoneWidth.Extended: 13793 if (offset === 0) { 13794 return 'Z'; 13795 } else { 13796 return (zone >= 0 ? '+' : '') + padNumber(hours, 2, minusSign) + ':' + padNumber(Math.abs(zone % 60), 2, minusSign); 13797 } 13798 13799 default: 13800 throw new Error(`Unknown zone width "${width}"`); 13801 } 13802 }; 13803} 13804 13805const JANUARY = 0; 13806const THURSDAY = 4; 13807 13808function getFirstThursdayOfYear(year) { 13809 const firstDayOfYear = createDate(year, JANUARY, 1).getDay(); 13810 return createDate(year, 0, 1 + (firstDayOfYear <= THURSDAY ? THURSDAY : THURSDAY + 7) - firstDayOfYear); 13811} 13812 13813function getThursdayThisWeek(datetime) { 13814 return createDate(datetime.getFullYear(), datetime.getMonth(), datetime.getDate() + (THURSDAY - datetime.getDay())); 13815} 13816 13817function weekGetter(size, monthBased = false) { 13818 return function (date, locale) { 13819 let result; 13820 13821 if (monthBased) { 13822 const nbDaysBefore1stDayOfMonth = new Date(date.getFullYear(), date.getMonth(), 1).getDay() - 1; 13823 const today = date.getDate(); 13824 result = 1 + Math.floor((today + nbDaysBefore1stDayOfMonth) / 7); 13825 } else { 13826 const thisThurs = getThursdayThisWeek(date); // Some days of a year are part of next year according to ISO 8601. 13827 // Compute the firstThurs from the year of this week's Thursday 13828 13829 const firstThurs = getFirstThursdayOfYear(thisThurs.getFullYear()); 13830 const diff = thisThurs.getTime() - firstThurs.getTime(); 13831 result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week 13832 } 13833 13834 return padNumber(result, size, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign)); 13835 }; 13836} 13837/** 13838 * Returns a date formatter that provides the week-numbering year for the input date. 13839 */ 13840 13841 13842function weekNumberingYearGetter(size, trim = false) { 13843 return function (date, locale) { 13844 const thisThurs = getThursdayThisWeek(date); 13845 const weekNumberingYear = thisThurs.getFullYear(); 13846 return padNumber(weekNumberingYear, size, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign), trim); 13847 }; 13848} 13849 13850const DATE_FORMATS = {}; // Based on CLDR formats: 13851// See complete list: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table 13852// See also explanations: http://cldr.unicode.org/translation/date-time 13853// TODO(ocombe): support all missing cldr formats: U, Q, D, F, e, j, J, C, A, v, V, X, x 13854 13855function getDateFormatter(format) { 13856 if (DATE_FORMATS[format]) { 13857 return DATE_FORMATS[format]; 13858 } 13859 13860 let formatter; 13861 13862 switch (format) { 13863 // Era name (AD/BC) 13864 case 'G': 13865 case 'GG': 13866 case 'GGG': 13867 formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Abbreviated); 13868 break; 13869 13870 case 'GGGG': 13871 formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Wide); 13872 break; 13873 13874 case 'GGGGG': 13875 formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Narrow); 13876 break; 13877 // 1 digit representation of the year, e.g. (AD 1 => 1, AD 199 => 199) 13878 13879 case 'y': 13880 formatter = dateGetter(DateType.FullYear, 1, 0, false, true); 13881 break; 13882 // 2 digit representation of the year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10) 13883 13884 case 'yy': 13885 formatter = dateGetter(DateType.FullYear, 2, 0, true, true); 13886 break; 13887 // 3 digit representation of the year, padded (000-999). (e.g. AD 2001 => 01, AD 2010 => 10) 13888 13889 case 'yyy': 13890 formatter = dateGetter(DateType.FullYear, 3, 0, false, true); 13891 break; 13892 // 4 digit representation of the year (e.g. AD 1 => 0001, AD 2010 => 2010) 13893 13894 case 'yyyy': 13895 formatter = dateGetter(DateType.FullYear, 4, 0, false, true); 13896 break; 13897 // 1 digit representation of the week-numbering year, e.g. (AD 1 => 1, AD 199 => 199) 13898 13899 case 'Y': 13900 formatter = weekNumberingYearGetter(1); 13901 break; 13902 // 2 digit representation of the week-numbering year, padded (00-99). (e.g. AD 2001 => 01, AD 13903 // 2010 => 10) 13904 13905 case 'YY': 13906 formatter = weekNumberingYearGetter(2, true); 13907 break; 13908 // 3 digit representation of the week-numbering year, padded (000-999). (e.g. AD 1 => 001, AD 13909 // 2010 => 2010) 13910 13911 case 'YYY': 13912 formatter = weekNumberingYearGetter(3); 13913 break; 13914 // 4 digit representation of the week-numbering year (e.g. AD 1 => 0001, AD 2010 => 2010) 13915 13916 case 'YYYY': 13917 formatter = weekNumberingYearGetter(4); 13918 break; 13919 // Month of the year (1-12), numeric 13920 13921 case 'M': 13922 case 'L': 13923 formatter = dateGetter(DateType.Month, 1, 1); 13924 break; 13925 13926 case 'MM': 13927 case 'LL': 13928 formatter = dateGetter(DateType.Month, 2, 1); 13929 break; 13930 // Month of the year (January, ...), string, format 13931 13932 case 'MMM': 13933 formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Abbreviated); 13934 break; 13935 13936 case 'MMMM': 13937 formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Wide); 13938 break; 13939 13940 case 'MMMMM': 13941 formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Narrow); 13942 break; 13943 // Month of the year (January, ...), string, standalone 13944 13945 case 'LLL': 13946 formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Abbreviated, FormStyle.Standalone); 13947 break; 13948 13949 case 'LLLL': 13950 formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Wide, FormStyle.Standalone); 13951 break; 13952 13953 case 'LLLLL': 13954 formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Narrow, FormStyle.Standalone); 13955 break; 13956 // Week of the year (1, ... 52) 13957 13958 case 'w': 13959 formatter = weekGetter(1); 13960 break; 13961 13962 case 'ww': 13963 formatter = weekGetter(2); 13964 break; 13965 // Week of the month (1, ...) 13966 13967 case 'W': 13968 formatter = weekGetter(1, true); 13969 break; 13970 // Day of the month (1-31) 13971 13972 case 'd': 13973 formatter = dateGetter(DateType.Date, 1); 13974 break; 13975 13976 case 'dd': 13977 formatter = dateGetter(DateType.Date, 2); 13978 break; 13979 // Day of the Week StandAlone (1, 1, Mon, Monday, M, Mo) 13980 13981 case 'c': 13982 case 'cc': 13983 formatter = dateGetter(DateType.Day, 1); 13984 break; 13985 13986 case 'ccc': 13987 formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Abbreviated, FormStyle.Standalone); 13988 break; 13989 13990 case 'cccc': 13991 formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Wide, FormStyle.Standalone); 13992 break; 13993 13994 case 'ccccc': 13995 formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Narrow, FormStyle.Standalone); 13996 break; 13997 13998 case 'cccccc': 13999 formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Short, FormStyle.Standalone); 14000 break; 14001 // Day of the Week 14002 14003 case 'E': 14004 case 'EE': 14005 case 'EEE': 14006 formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Abbreviated); 14007 break; 14008 14009 case 'EEEE': 14010 formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Wide); 14011 break; 14012 14013 case 'EEEEE': 14014 formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Narrow); 14015 break; 14016 14017 case 'EEEEEE': 14018 formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Short); 14019 break; 14020 // Generic period of the day (am-pm) 14021 14022 case 'a': 14023 case 'aa': 14024 case 'aaa': 14025 formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated); 14026 break; 14027 14028 case 'aaaa': 14029 formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide); 14030 break; 14031 14032 case 'aaaaa': 14033 formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow); 14034 break; 14035 // Extended period of the day (midnight, at night, ...), standalone 14036 14037 case 'b': 14038 case 'bb': 14039 case 'bbb': 14040 formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated, FormStyle.Standalone, true); 14041 break; 14042 14043 case 'bbbb': 14044 formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide, FormStyle.Standalone, true); 14045 break; 14046 14047 case 'bbbbb': 14048 formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow, FormStyle.Standalone, true); 14049 break; 14050 // Extended period of the day (midnight, night, ...), standalone 14051 14052 case 'B': 14053 case 'BB': 14054 case 'BBB': 14055 formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated, FormStyle.Format, true); 14056 break; 14057 14058 case 'BBBB': 14059 formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide, FormStyle.Format, true); 14060 break; 14061 14062 case 'BBBBB': 14063 formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow, FormStyle.Format, true); 14064 break; 14065 // Hour in AM/PM, (1-12) 14066 14067 case 'h': 14068 formatter = dateGetter(DateType.Hours, 1, -12); 14069 break; 14070 14071 case 'hh': 14072 formatter = dateGetter(DateType.Hours, 2, -12); 14073 break; 14074 // Hour of the day (0-23) 14075 14076 case 'H': 14077 formatter = dateGetter(DateType.Hours, 1); 14078 break; 14079 // Hour in day, padded (00-23) 14080 14081 case 'HH': 14082 formatter = dateGetter(DateType.Hours, 2); 14083 break; 14084 // Minute of the hour (0-59) 14085 14086 case 'm': 14087 formatter = dateGetter(DateType.Minutes, 1); 14088 break; 14089 14090 case 'mm': 14091 formatter = dateGetter(DateType.Minutes, 2); 14092 break; 14093 // Second of the minute (0-59) 14094 14095 case 's': 14096 formatter = dateGetter(DateType.Seconds, 1); 14097 break; 14098 14099 case 'ss': 14100 formatter = dateGetter(DateType.Seconds, 2); 14101 break; 14102 // Fractional second 14103 14104 case 'S': 14105 formatter = dateGetter(DateType.FractionalSeconds, 1); 14106 break; 14107 14108 case 'SS': 14109 formatter = dateGetter(DateType.FractionalSeconds, 2); 14110 break; 14111 14112 case 'SSS': 14113 formatter = dateGetter(DateType.FractionalSeconds, 3); 14114 break; 14115 // Timezone ISO8601 short format (-0430) 14116 14117 case 'Z': 14118 case 'ZZ': 14119 case 'ZZZ': 14120 formatter = timeZoneGetter(ZoneWidth.Short); 14121 break; 14122 // Timezone ISO8601 extended format (-04:30) 14123 14124 case 'ZZZZZ': 14125 formatter = timeZoneGetter(ZoneWidth.Extended); 14126 break; 14127 // Timezone GMT short format (GMT+4) 14128 14129 case 'O': 14130 case 'OO': 14131 case 'OOO': // Should be location, but fallback to format O instead because we don't have the data yet 14132 14133 case 'z': 14134 case 'zz': 14135 case 'zzz': 14136 formatter = timeZoneGetter(ZoneWidth.ShortGMT); 14137 break; 14138 // Timezone GMT long format (GMT+0430) 14139 14140 case 'OOOO': 14141 case 'ZZZZ': // Should be location, but fallback to format O instead because we don't have the data yet 14142 14143 case 'zzzz': 14144 formatter = timeZoneGetter(ZoneWidth.Long); 14145 break; 14146 14147 default: 14148 return null; 14149 } 14150 14151 DATE_FORMATS[format] = formatter; 14152 return formatter; 14153} 14154 14155function timezoneToOffset(timezone, fallback) { 14156 // Support: IE 11 only, Edge 13-15+ 14157 // IE/Edge do not "understand" colon (`:`) in timezone 14158 timezone = timezone.replace(/:/g, ''); 14159 const requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; 14160 return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset; 14161} 14162 14163function addDateMinutes(date, minutes) { 14164 date = new Date(date.getTime()); 14165 date.setMinutes(date.getMinutes() + minutes); 14166 return date; 14167} 14168 14169function convertTimezoneToLocal(date, timezone, reverse) { 14170 const reverseValue = reverse ? -1 : 1; 14171 const dateTimezoneOffset = date.getTimezoneOffset(); 14172 const timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset); 14173 return addDateMinutes(date, reverseValue * (timezoneOffset - dateTimezoneOffset)); 14174} 14175/** 14176 * Converts a value to date. 14177 * 14178 * Supported input formats: 14179 * - `Date` 14180 * - number: timestamp 14181 * - string: numeric (e.g. "1234"), ISO and date strings in a format supported by 14182 * [Date.parse()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse). 14183 * Note: ISO strings without time return a date without timeoffset. 14184 * 14185 * Throws if unable to convert to a date. 14186 */ 14187 14188 14189function toDate(value) { 14190 if (isDate(value)) { 14191 return value; 14192 } 14193 14194 if (typeof value === 'number' && !isNaN(value)) { 14195 return new Date(value); 14196 } 14197 14198 if (typeof value === 'string') { 14199 value = value.trim(); 14200 14201 if (/^(\d{4}(-\d{1,2}(-\d{1,2})?)?)$/.test(value)) { 14202 /* For ISO Strings without time the day, month and year must be extracted from the ISO String 14203 before Date creation to avoid time offset and errors in the new Date. 14204 If we only replace '-' with ',' in the ISO String ("2015,01,01"), and try to create a new 14205 date, some browsers (e.g. IE 9) will throw an invalid Date error. 14206 If we leave the '-' ("2015-01-01") and try to create a new Date("2015-01-01") the timeoffset 14207 is applied. 14208 Note: ISO months are 0 for January, 1 for February, ... */ 14209 const [y, m = 1, d = 1] = value.split('-').map(val => +val); 14210 return createDate(y, m - 1, d); 14211 } 14212 14213 const parsedNb = parseFloat(value); // any string that only contains numbers, like "1234" but not like "1234hello" 14214 14215 if (!isNaN(value - parsedNb)) { 14216 return new Date(parsedNb); 14217 } 14218 14219 let match; 14220 14221 if (match = value.match(ISO8601_DATE_REGEX)) { 14222 return isoStringToDate(match); 14223 } 14224 } 14225 14226 const date = new Date(value); 14227 14228 if (!isDate(date)) { 14229 throw new Error(`Unable to convert "${value}" into a date`); 14230 } 14231 14232 return date; 14233} 14234/** 14235 * Converts a date in ISO8601 to a Date. 14236 * Used instead of `Date.parse` because of browser discrepancies. 14237 */ 14238 14239 14240function isoStringToDate(match) { 14241 const date = new Date(0); 14242 let tzHour = 0; 14243 let tzMin = 0; // match[8] means that the string contains "Z" (UTC) or a timezone like "+01:00" or "+0100" 14244 14245 const dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear; 14246 const timeSetter = match[8] ? date.setUTCHours : date.setHours; // if there is a timezone defined like "+01:00" or "+0100" 14247 14248 if (match[9]) { 14249 tzHour = Number(match[9] + match[10]); 14250 tzMin = Number(match[9] + match[11]); 14251 } 14252 14253 dateSetter.call(date, Number(match[1]), Number(match[2]) - 1, Number(match[3])); 14254 const h = Number(match[4] || 0) - tzHour; 14255 const m = Number(match[5] || 0) - tzMin; 14256 const s = Number(match[6] || 0); // The ECMAScript specification (https://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.11) 14257 // defines that `DateTime` milliseconds should always be rounded down, so that `999.9ms` 14258 // becomes `999ms`. 14259 14260 const ms = Math.floor(parseFloat('0.' + (match[7] || 0)) * 1000); 14261 timeSetter.call(date, h, m, s, ms); 14262 return date; 14263} 14264 14265function isDate(value) { 14266 return value instanceof Date && !isNaN(value.valueOf()); 14267} 14268/** 14269 * @license 14270 * Copyright Google LLC All Rights Reserved. 14271 * 14272 * Use of this source code is governed by an MIT-style license that can be 14273 * found in the LICENSE file at https://angular.io/license 14274 */ 14275 14276 14277const NUMBER_FORMAT_REGEXP = /^(\d+)?\.((\d+)(-(\d+))?)?$/; 14278const MAX_DIGITS = 22; 14279const DECIMAL_SEP = '.'; 14280const ZERO_CHAR = '0'; 14281const PATTERN_SEP = ';'; 14282const GROUP_SEP = ','; 14283const DIGIT_CHAR = '#'; 14284const CURRENCY_CHAR = '¤'; 14285const PERCENT_CHAR = '%'; 14286/** 14287 * Transforms a number to a locale string based on a style and a format. 14288 */ 14289 14290function formatNumberToLocaleString(value, pattern, locale, groupSymbol, decimalSymbol, digitsInfo, isPercent = false) { 14291 let formattedText = ''; 14292 let isZero = false; 14293 14294 if (!isFinite(value)) { 14295 formattedText = getLocaleNumberSymbol(locale, NumberSymbol.Infinity); 14296 } else { 14297 let parsedNumber = parseNumber(value); 14298 14299 if (isPercent) { 14300 parsedNumber = toPercent(parsedNumber); 14301 } 14302 14303 let minInt = pattern.minInt; 14304 let minFraction = pattern.minFrac; 14305 let maxFraction = pattern.maxFrac; 14306 14307 if (digitsInfo) { 14308 const parts = digitsInfo.match(NUMBER_FORMAT_REGEXP); 14309 14310 if (parts === null) { 14311 throw new Error(`${digitsInfo} is not a valid digit info`); 14312 } 14313 14314 const minIntPart = parts[1]; 14315 const minFractionPart = parts[3]; 14316 const maxFractionPart = parts[5]; 14317 14318 if (minIntPart != null) { 14319 minInt = parseIntAutoRadix(minIntPart); 14320 } 14321 14322 if (minFractionPart != null) { 14323 minFraction = parseIntAutoRadix(minFractionPart); 14324 } 14325 14326 if (maxFractionPart != null) { 14327 maxFraction = parseIntAutoRadix(maxFractionPart); 14328 } else if (minFractionPart != null && minFraction > maxFraction) { 14329 maxFraction = minFraction; 14330 } 14331 } 14332 14333 roundNumber(parsedNumber, minFraction, maxFraction); 14334 let digits = parsedNumber.digits; 14335 let integerLen = parsedNumber.integerLen; 14336 const exponent = parsedNumber.exponent; 14337 let decimals = []; 14338 isZero = digits.every(d => !d); // pad zeros for small numbers 14339 14340 for (; integerLen < minInt; integerLen++) { 14341 digits.unshift(0); 14342 } // pad zeros for small numbers 14343 14344 14345 for (; integerLen < 0; integerLen++) { 14346 digits.unshift(0); 14347 } // extract decimals digits 14348 14349 14350 if (integerLen > 0) { 14351 decimals = digits.splice(integerLen, digits.length); 14352 } else { 14353 decimals = digits; 14354 digits = [0]; 14355 } // format the integer digits with grouping separators 14356 14357 14358 const groups = []; 14359 14360 if (digits.length >= pattern.lgSize) { 14361 groups.unshift(digits.splice(-pattern.lgSize, digits.length).join('')); 14362 } 14363 14364 while (digits.length > pattern.gSize) { 14365 groups.unshift(digits.splice(-pattern.gSize, digits.length).join('')); 14366 } 14367 14368 if (digits.length) { 14369 groups.unshift(digits.join('')); 14370 } 14371 14372 formattedText = groups.join(getLocaleNumberSymbol(locale, groupSymbol)); // append the decimal digits 14373 14374 if (decimals.length) { 14375 formattedText += getLocaleNumberSymbol(locale, decimalSymbol) + decimals.join(''); 14376 } 14377 14378 if (exponent) { 14379 formattedText += getLocaleNumberSymbol(locale, NumberSymbol.Exponential) + '+' + exponent; 14380 } 14381 } 14382 14383 if (value < 0 && !isZero) { 14384 formattedText = pattern.negPre + formattedText + pattern.negSuf; 14385 } else { 14386 formattedText = pattern.posPre + formattedText + pattern.posSuf; 14387 } 14388 14389 return formattedText; 14390} 14391/** 14392 * @ngModule CommonModule 14393 * @description 14394 * 14395 * Formats a number as currency using locale rules. 14396 * 14397 * @param value The number to format. 14398 * @param locale A locale code for the locale format rules to use. 14399 * @param currency A string containing the currency symbol or its name, 14400 * such as "$" or "Canadian Dollar". Used in output string, but does not affect the operation 14401 * of the function. 14402 * @param currencyCode The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) 14403 * currency code, such as `USD` for the US dollar and `EUR` for the euro. 14404 * Used to determine the number of digits in the decimal part. 14405 * @param digitsInfo Decimal representation options, specified by a string in the following format: 14406 * `{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}`. See `DecimalPipe` for more details. 14407 * 14408 * @returns The formatted currency value. 14409 * 14410 * @see `formatNumber()` 14411 * @see `DecimalPipe` 14412 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 14413 * 14414 * @publicApi 14415 */ 14416 14417 14418function formatCurrency(value, locale, currency, currencyCode, digitsInfo) { 14419 const format = getLocaleNumberFormat(locale, NumberFormatStyle.Currency); 14420 const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign)); 14421 pattern.minFrac = getNumberOfCurrencyDigits(currencyCode); 14422 pattern.maxFrac = pattern.minFrac; 14423 const res = formatNumberToLocaleString(value, pattern, locale, NumberSymbol.CurrencyGroup, NumberSymbol.CurrencyDecimal, digitsInfo); 14424 return res.replace(CURRENCY_CHAR, currency) // if we have 2 time the currency character, the second one is ignored 14425 .replace(CURRENCY_CHAR, '') // If there is a spacing between currency character and the value and 14426 // the currency character is suppressed by passing an empty string, the 14427 // spacing character would remain as part of the string. Then we 14428 // should remove it. 14429 .trim(); 14430} 14431/** 14432 * @ngModule CommonModule 14433 * @description 14434 * 14435 * Formats a number as a percentage according to locale rules. 14436 * 14437 * @param value The number to format. 14438 * @param locale A locale code for the locale format rules to use. 14439 * @param digitsInfo Decimal representation options, specified by a string in the following format: 14440 * `{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}`. See `DecimalPipe` for more details. 14441 * 14442 * @returns The formatted percentage value. 14443 * 14444 * @see `formatNumber()` 14445 * @see `DecimalPipe` 14446 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 14447 * @publicApi 14448 * 14449 */ 14450 14451 14452function formatPercent(value, locale, digitsInfo) { 14453 const format = getLocaleNumberFormat(locale, NumberFormatStyle.Percent); 14454 const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign)); 14455 const res = formatNumberToLocaleString(value, pattern, locale, NumberSymbol.Group, NumberSymbol.Decimal, digitsInfo, true); 14456 return res.replace(new RegExp(PERCENT_CHAR, 'g'), getLocaleNumberSymbol(locale, NumberSymbol.PercentSign)); 14457} 14458/** 14459 * @ngModule CommonModule 14460 * @description 14461 * 14462 * Formats a number as text, with group sizing, separator, and other 14463 * parameters based on the locale. 14464 * 14465 * @param value The number to format. 14466 * @param locale A locale code for the locale format rules to use. 14467 * @param digitsInfo Decimal representation options, specified by a string in the following format: 14468 * `{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}`. See `DecimalPipe` for more details. 14469 * 14470 * @returns The formatted text string. 14471 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 14472 * 14473 * @publicApi 14474 */ 14475 14476 14477function formatNumber(value, locale, digitsInfo) { 14478 const format = getLocaleNumberFormat(locale, NumberFormatStyle.Decimal); 14479 const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign)); 14480 return formatNumberToLocaleString(value, pattern, locale, NumberSymbol.Group, NumberSymbol.Decimal, digitsInfo); 14481} 14482 14483function parseNumberFormat(format, minusSign = '-') { 14484 const p = { 14485 minInt: 1, 14486 minFrac: 0, 14487 maxFrac: 0, 14488 posPre: '', 14489 posSuf: '', 14490 negPre: '', 14491 negSuf: '', 14492 gSize: 0, 14493 lgSize: 0 14494 }; 14495 const patternParts = format.split(PATTERN_SEP); 14496 const positive = patternParts[0]; 14497 const negative = patternParts[1]; 14498 const positiveParts = positive.indexOf(DECIMAL_SEP) !== -1 ? positive.split(DECIMAL_SEP) : [positive.substring(0, positive.lastIndexOf(ZERO_CHAR) + 1), positive.substring(positive.lastIndexOf(ZERO_CHAR) + 1)], 14499 integer = positiveParts[0], 14500 fraction = positiveParts[1] || ''; 14501 p.posPre = integer.substring(0, integer.indexOf(DIGIT_CHAR)); 14502 14503 for (let i = 0; i < fraction.length; i++) { 14504 const ch = fraction.charAt(i); 14505 14506 if (ch === ZERO_CHAR) { 14507 p.minFrac = p.maxFrac = i + 1; 14508 } else if (ch === DIGIT_CHAR) { 14509 p.maxFrac = i + 1; 14510 } else { 14511 p.posSuf += ch; 14512 } 14513 } 14514 14515 const groups = integer.split(GROUP_SEP); 14516 p.gSize = groups[1] ? groups[1].length : 0; 14517 p.lgSize = groups[2] || groups[1] ? (groups[2] || groups[1]).length : 0; 14518 14519 if (negative) { 14520 const trunkLen = positive.length - p.posPre.length - p.posSuf.length, 14521 pos = negative.indexOf(DIGIT_CHAR); 14522 p.negPre = negative.substring(0, pos).replace(/'/g, ''); 14523 p.negSuf = negative.slice(pos + trunkLen).replace(/'/g, ''); 14524 } else { 14525 p.negPre = minusSign + p.posPre; 14526 p.negSuf = p.posSuf; 14527 } 14528 14529 return p; 14530} // Transforms a parsed number into a percentage by multiplying it by 100 14531 14532 14533function toPercent(parsedNumber) { 14534 // if the number is 0, don't do anything 14535 if (parsedNumber.digits[0] === 0) { 14536 return parsedNumber; 14537 } // Getting the current number of decimals 14538 14539 14540 const fractionLen = parsedNumber.digits.length - parsedNumber.integerLen; 14541 14542 if (parsedNumber.exponent) { 14543 parsedNumber.exponent += 2; 14544 } else { 14545 if (fractionLen === 0) { 14546 parsedNumber.digits.push(0, 0); 14547 } else if (fractionLen === 1) { 14548 parsedNumber.digits.push(0); 14549 } 14550 14551 parsedNumber.integerLen += 2; 14552 } 14553 14554 return parsedNumber; 14555} 14556/** 14557 * Parses a number. 14558 * Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/ 14559 */ 14560 14561 14562function parseNumber(num) { 14563 let numStr = Math.abs(num) + ''; 14564 let exponent = 0, 14565 digits, 14566 integerLen; 14567 let i, j, zeros; // Decimal point? 14568 14569 if ((integerLen = numStr.indexOf(DECIMAL_SEP)) > -1) { 14570 numStr = numStr.replace(DECIMAL_SEP, ''); 14571 } // Exponential form? 14572 14573 14574 if ((i = numStr.search(/e/i)) > 0) { 14575 // Work out the exponent. 14576 if (integerLen < 0) integerLen = i; 14577 integerLen += +numStr.slice(i + 1); 14578 numStr = numStr.substring(0, i); 14579 } else if (integerLen < 0) { 14580 // There was no decimal point or exponent so it is an integer. 14581 integerLen = numStr.length; 14582 } // Count the number of leading zeros. 14583 14584 14585 for (i = 0; numStr.charAt(i) === ZERO_CHAR; i++) { 14586 /* empty */ 14587 } 14588 14589 if (i === (zeros = numStr.length)) { 14590 // The digits are all zero. 14591 digits = [0]; 14592 integerLen = 1; 14593 } else { 14594 // Count the number of trailing zeros 14595 zeros--; 14596 14597 while (numStr.charAt(zeros) === ZERO_CHAR) zeros--; // Trailing zeros are insignificant so ignore them 14598 14599 14600 integerLen -= i; 14601 digits = []; // Convert string to array of digits without leading/trailing zeros. 14602 14603 for (j = 0; i <= zeros; i++, j++) { 14604 digits[j] = Number(numStr.charAt(i)); 14605 } 14606 } // If the number overflows the maximum allowed digits then use an exponent. 14607 14608 14609 if (integerLen > MAX_DIGITS) { 14610 digits = digits.splice(0, MAX_DIGITS - 1); 14611 exponent = integerLen - 1; 14612 integerLen = 1; 14613 } 14614 14615 return { 14616 digits, 14617 exponent, 14618 integerLen 14619 }; 14620} 14621/** 14622 * Round the parsed number to the specified number of decimal places 14623 * This function changes the parsedNumber in-place 14624 */ 14625 14626 14627function roundNumber(parsedNumber, minFrac, maxFrac) { 14628 if (minFrac > maxFrac) { 14629 throw new Error(`The minimum number of digits after fraction (${minFrac}) is higher than the maximum (${maxFrac}).`); 14630 } 14631 14632 let digits = parsedNumber.digits; 14633 let fractionLen = digits.length - parsedNumber.integerLen; 14634 const fractionSize = Math.min(Math.max(minFrac, fractionLen), maxFrac); // The index of the digit to where rounding is to occur 14635 14636 let roundAt = fractionSize + parsedNumber.integerLen; 14637 let digit = digits[roundAt]; 14638 14639 if (roundAt > 0) { 14640 // Drop fractional digits beyond `roundAt` 14641 digits.splice(Math.max(parsedNumber.integerLen, roundAt)); // Set non-fractional digits beyond `roundAt` to 0 14642 14643 for (let j = roundAt; j < digits.length; j++) { 14644 digits[j] = 0; 14645 } 14646 } else { 14647 // We rounded to zero so reset the parsedNumber 14648 fractionLen = Math.max(0, fractionLen); 14649 parsedNumber.integerLen = 1; 14650 digits.length = Math.max(1, roundAt = fractionSize + 1); 14651 digits[0] = 0; 14652 14653 for (let i = 1; i < roundAt; i++) digits[i] = 0; 14654 } 14655 14656 if (digit >= 5) { 14657 if (roundAt - 1 < 0) { 14658 for (let k = 0; k > roundAt; k--) { 14659 digits.unshift(0); 14660 parsedNumber.integerLen++; 14661 } 14662 14663 digits.unshift(1); 14664 parsedNumber.integerLen++; 14665 } else { 14666 digits[roundAt - 1]++; 14667 } 14668 } // Pad out with zeros to get the required fraction length 14669 14670 14671 for (; fractionLen < Math.max(0, fractionSize); fractionLen++) digits.push(0); 14672 14673 let dropTrailingZeros = fractionSize !== 0; // Minimal length = nb of decimals required + current nb of integers 14674 // Any number besides that is optional and can be removed if it's a trailing 0 14675 14676 const minLen = minFrac + parsedNumber.integerLen; // Do any carrying, e.g. a digit was rounded up to 10 14677 14678 const carry = digits.reduceRight(function (carry, d, i, digits) { 14679 d = d + carry; 14680 digits[i] = d < 10 ? d : d - 10; // d % 10 14681 14682 if (dropTrailingZeros) { 14683 // Do not keep meaningless fractional trailing zeros (e.g. 15.52000 --> 15.52) 14684 if (digits[i] === 0 && i >= minLen) { 14685 digits.pop(); 14686 } else { 14687 dropTrailingZeros = false; 14688 } 14689 } 14690 14691 return d >= 10 ? 1 : 0; // Math.floor(d / 10); 14692 }, 0); 14693 14694 if (carry) { 14695 digits.unshift(carry); 14696 parsedNumber.integerLen++; 14697 } 14698} 14699 14700function parseIntAutoRadix(text) { 14701 const result = parseInt(text); 14702 14703 if (isNaN(result)) { 14704 throw new Error('Invalid integer literal when parsing ' + text); 14705 } 14706 14707 return result; 14708} 14709/** 14710 * @license 14711 * Copyright Google LLC All Rights Reserved. 14712 * 14713 * Use of this source code is governed by an MIT-style license that can be 14714 * found in the LICENSE file at https://angular.io/license 14715 */ 14716 14717/** 14718 * @publicApi 14719 */ 14720 14721 14722class NgLocalization {} 14723 14724NgLocalization.ɵfac = function NgLocalization_Factory(t) { 14725 return new (t || NgLocalization)(); 14726}; 14727 14728NgLocalization.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 14729 token: NgLocalization, 14730 factory: function NgLocalization_Factory(t) { 14731 let r = null; 14732 14733 if (t) { 14734 r = new t(); 14735 } else { 14736 r = (locale =>
14736 new NgLocaleLocalization(locale))(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID)); 14737 } 14738 14739 return r; 14740 }, 14741 providedIn: 'root' 14742}); 14743 14744(function () { 14745 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgLocalization, [{ 14746 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 14747 args: [{ 14748 providedIn: 'root', 14749 useFactory: locale => new NgLocaleLocalization(locale), 14750 deps: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID] 14751 }] 14752 }], null, null); 14753})(); 14754/** 14755 * Returns the plural category for a given value. 14756 * - "=value" when the case exists, 14757 * - the plural category otherwise 14758 */ 14759 14760 14761function getPluralCategory(value, cases, ngLocalization, locale) { 14762 let key = `=${value}`; 14763 14764 if (cases.indexOf(key) > -1) { 14765 return key; 14766 } 14767 14768 key = ngLocalization.getPluralCategory(value, locale); 14769 14770 if (cases.indexOf(key) > -1) { 14771 return key; 14772 } 14773 14774 if (cases.indexOf('other') > -1) { 14775 return 'other'; 14776 } 14777 14778 throw new Error(`No plural message found for value "${value}"`); 14779} 14780/** 14781 * Returns the plural case based on the locale 14782 * 14783 * @publicApi 14784 */ 14785 14786 14787class NgLocaleLocalization extends NgLocalization { 14788 constructor(locale) { 14789 super(); 14790 this.locale = locale; 14791 } 14792 14793 getPluralCategory(value, locale) { 14794 const plural = getLocalePluralCase(locale || this.locale)(value); 14795 14796 switch (plural) { 14797 case Plural.Zero: 14798 return 'zero'; 14799 14800 case Plural.One: 14801 return 'one'; 14802 14803 case Plural.Two: 14804 return 'two'; 14805 14806 case Plural.Few: 14807 return 'few'; 14808 14809 case Plural.Many: 14810 return 'many'; 14811 14812 default: 14813 return 'other'; 14814 } 14815 } 14816 14817} 14818 14819NgLocaleLocalization.ɵfac = function NgLocaleLocalization_Factory(t) { 14820 return new (t || NgLocaleLocalization)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID)); 14821}; 14822 14823NgLocaleLocalization.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 14824 token: NgLocaleLocalization, 14825 factory: NgLocaleLocalization.ɵfac 14826}); 14827 14828(function () { 14829 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgLocaleLocalization, [{ 14830 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable 14831 }], function () { 14832 return [{ 14833 type: undefined, 14834 decorators: [{ 14835 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 14836 args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID] 14837 }] 14838 }]; 14839 }, null); 14840})(); 14841/** 14842 * @license 14843 * Copyright Google LLC All Rights Reserved. 14844 * 14845 * Use of this source code is governed by an MIT-style license that can be 14846 * found in the LICENSE file at https://angular.io/license 14847 */ 14848 14849/** 14850 * Register global data to be used internally by Angular. See the 14851 * ["I18n guide"](guide/i18n-common-format-data-locale) to know how to import additional locale 14852 * data. 14853 * 14854 * The signature registerLocaleData(data: any, extraData?: any) is deprecated since v5.1 14855 * 14856 * @publicApi 14857 */ 14858 14859 14860function registerLocaleData(data, localeId, extraData) { 14861 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵregisterLocaleData"])(data, localeId, extraData); 14862} 14863/** 14864 * @license 14865 * Copyright Google LLC All Rights Reserved. 14866 * 14867 * Use of this source code is governed by an MIT-style license that can be 14868 * found in the LICENSE file at https://angular.io/license 14869 */ 14870 14871 14872function parseCookieValue(cookieStr, name) { 14873 name = encodeURIComponent(name); 14874 14875 for (const cookie of cookieStr.split(';')) { 14876 const eqIndex = cookie.indexOf('='); 14877 const [cookieName, cookieValue] = eqIndex == -1 ? [cookie, ''] : [cookie.slice(0, eqIndex), cookie.slice(eqIndex + 1)]; 14878 14879 if (cookieName.trim() === name) { 14880 return decodeURIComponent(cookieValue); 14881 } 14882 } 14883 14884 return null; 14885} 14886/** 14887 * @license 14888 * Copyright Google LLC All Rights Reserved. 14889 * 14890 * Use of this source code is governed by an MIT-style license that can be 14891 * found in the LICENSE file at https://angular.io/license 14892 */ 14893 14894/** 14895 * @ngModule CommonModule 14896 * 14897 * @usageNotes 14898 * ``` 14899 * <some-element [ngClass]="'first second'">...</some-element> 14900 * 14901 * <some-element [ngClass]="['first', 'second']">...</some-element> 14902 * 14903 * <some-element [ngClass]="{'first': true, 'second': true, 'third': false}">...</some-element> 14904 *
14905 * <some-element [ngClass]="stringExp|arrayExp|objExp">...</some-element> 14906 * 14907 * <some-element [ngClass]="{'class1 class2 class3' : true}">...</some-element> 14908 * ``` 14909 * 14910 * @description 14911 * 14912 * Adds and removes CSS classes on an HTML element. 14913 * 14914 * The CSS classes are updated as follows, depending on the type of the expression evaluation: 14915 * - `string` - the CSS classes listed in the string (space delimited) are added, 14916 * - `Array` - the CSS classes declared as Array elements are added, 14917 * - `Object` - keys are CSS classes that get added when the expression given in the value 14918 * evaluates to a truthy value, otherwise they are removed. 14919 * 14920 * @publicApi 14921 */ 14922 14923 14924class NgClass { 14925 constructor(_iterableDiffers, _keyValueDiffers, _ngEl, _renderer) { 14926 this._iterableDiffers = _iterableDiffers; 14927 this._keyValueDiffers = _keyValueDiffers; 14928 this._ngEl = _ngEl; 14929 this._renderer = _renderer; 14930 this._iterableDiffer = null; 14931 this._keyValueDiffer = null; 14932 this._initialClasses = []; 14933 this._rawClass = null; 14934 } 14935 14936 set klass(value) { 14937 this._removeClasses(this._initialClasses); 14938 14939 this._initialClasses = typeof value === 'string' ? value.split(/\s+/) : []; 14940 14941 this._applyClasses(this._initialClasses); 14942 14943 this._applyClasses(this._rawClass); 14944 } 14945 14946 set ngClass(value) { 14947 this._removeClasses(this._rawClass); 14948 14949 this._applyClasses(this._initialClasses); 14950 14951 this._iterableDiffer = null; 14952 this._keyValueDiffer = null; 14953 this._rawClass = typeof value === 'string' ? value.split(/\s+/) : value; 14954 14955 if (this._rawClass) { 14956 if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisListLikeIterable"])(this._rawClass)) { 14957 this._iterableDiffer = this._iterableDiffers.find(this._rawClass).create(); 14958 } else { 14959 this._keyValueDiffer = this._keyValueDiffers.find(this._rawClass).create(); 14960 } 14961 } 14962 } 14963 14964 ngDoCheck() { 14965 if (this._iterableDiffer) { 14966 const iterableChanges = this._iterableDiffer.diff(this._rawClass); 14967 14968 if (iterableChanges) { 14969 this._applyIterableChanges(iterableChanges); 14970 } 14971 } else if (this._keyValueDiffer) { 14972 const keyValueChanges = this._keyValueDiffer.diff(this._rawClass); 14973 14974 if (keyValueChanges) { 14975 this._applyKeyValueChanges(keyValueChanges); 14976 } 14977 } 14978 } 14979 14980 _applyKeyValueChanges(changes) {
14981 changes.forEachAddedItem(record => this._toggleClass(record.key, record.currentValue)); 14982 changes.forEachChangedItem(record => this._toggleClass(record.key, record.currentValue)); 14983 changes.forEachRemovedItem(record => { 14984 if (record.previousValue) { 14985 this._toggleClass(record.key, false); 14986 } 14987 }); 14988 } 14989 14990 _applyIterableChanges(changes) { 14991 changes.forEachAddedItem(record => { 14992 if (typeof record.item === 'string') { 14993 this._toggleClass(record.item, true); 14994 } else { 14995 throw new Error(`NgClass can only toggle CSS classes expressed as strings, got ${(0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵstringify"])(record.item)}`); 14996 } 14997 }); 14998 changes.forEachRemovedItem(record => this._toggleClass(record.item, false)); 14999 } 15000 /** 15001 * Applies a collection of CSS classes to the DOM element. 15002 * 15003 * For argument of type Set and Array CSS class names contained in those collections are always 15004 * added. 15005 * For argument of type Map CSS class name in the map's key is toggled based on the value (added 15006 * for truthy and removed for falsy). 15007 */ 15008 15009 15010 _applyClasses(rawClassVal) { 15011 if (rawClassVal) { 15012 if (Array.isArray(rawClassVal) || rawClassVal instanceof Set) { 15013 rawClassVal.forEach(klass => this._toggleClass(klass, true)); 15014 } else { 15015 Object.keys(rawClassVal).forEach(klass => this._toggleClass(klass, !!rawClassVal[klass])); 15016 } 15017 } 15018 } 15019 /** 15020 * Removes a collection of CSS classes from the DOM element. This is mostly useful for cleanup 15021 * purposes. 15022 */ 15023 15024 15025 _removeClasses(rawClassVal) { 15026 if (rawClassVal) { 15027 if (Array.isArray(rawClassVal) || rawClassVal instanceof Set) { 15028 rawClassVal.forEach(klass => this._toggleClass(klass, false)); 15029 } else { 15030 Object.keys(rawClassVal).forEach(klass => this._toggleClass(klass, false)); 15031 } 15032 } 15033 } 15034 15035 _toggleClass(klass, enabled) { 15036 klass = klass.trim(); 15037 15038 if (klass) { 15039 klass.split(/\s+/g).forEach(klass => { 15040 if (enabled) { 15041 this._renderer.addClass(this._ngEl.nativeElement, klass); 15042 } else { 15043 this._renderer.removeClass(this._ngEl.nativeElement, klass); 15044 } 15045 }); 15046 } 15047 } 15048 15049} 15050 15051NgClass.ɵfac = function NgClass_Factory(t) { 15052 return new (t || NgClass)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.IterableDiffers), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.KeyValueDiffers), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2)); 15053}; 15054 15055NgClass.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 15056 type: NgClass, 15057 selectors: [["", "ngClass", ""]], 15058 inputs: { 15059 klass: ["class", "klass"], 15060 ngClass: "ngClass" 15061 }, 15062 standalone: true 15063}); 15064 15065(function () { 15066 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgClass, [{ 15067 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 15068 args: [{ 15069 selector: '[ngClass]', 15070 standalone: true 15071 }] 15072 }], function () { 15073 return [{ 15074 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.IterableDiffers 15075 }, { 15076 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.KeyValueDiffers 15077 }, { 15078 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef 15079 }, { 15080 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2 15081 }]; 15082 }, { 15083 klass: [{ 15084 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 15085 args: ['class'] 15086 }], 15087 ngClass: [{ 15088 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 15089 args: ['ngClass'] 15090 }] 15091 }); 15092})(); 15093/** 15094 * @license 15095 * Copyright Google LLC All Rights Reserved. 15096 * 15097 * Use of this source code is governed by an MIT-style license that can be 15098 * found in the LICENSE file at https://angular.io/license 15099 */ 15100 15101/** 15102 * Instantiates a {@link Component} type and inserts its Host View into the current View. 15103 * `NgComponentOutlet` provides a declarative approach for dynamic component creation. 15104 * 15105 * `NgComponentOutlet` requires a component type, if a falsy value is set the view will clear and 15106 * any existing component will be destroyed. 15107 * 15108 * @usageNotes 15109 * 15110 * ### Fine tune control 15111 * 15112 * You can control the component creation process by using the following optional attributes: 15113 * 15114 * * `ngComponentOutletInjector`: Optional custom {@link Injector} that will be used as parent for 15115 * the Component. Defaults to the injector of the current view container. 15116 * 15117 * * `ngComponentOutletContent`: Optional list of projectable nodes to insert into the content 15118 * section of the component, if it exists. 15119 * 15120 * * `ngComponentOutletNgModule`: Optional NgModule class reference to allow loading another 15121 * module dynamically, then loading a component from that module. 15122 * 15123 * * `ngComponentOutletNgModuleFactory`: Deprecated config option that allows providing optional 15124 * NgModule factory to allow loading another module dynamically, then loading a component from that 15125 * module. Use `ngComponentOutletNgModule` instead. 15126 * 15127 * ### Syntax 15128 * 15129 * Simple 15130 * ``` 15131 * <ng-container *ngComponentOutlet="componentTypeExpression"></ng-container> 15132 * ``` 15133 * 15134 * Customized injector/content 15135 * ``` 15136 * <ng-container *ngComponentOutlet="componentTypeExpression; 15137 * injector: injectorExpression; 15138 * content: contentNodesExpression;"> 15139 * </ng-container> 15140 * ``` 15141 * 15142 * Customized NgModule reference 15143 * ``` 15144 * <ng-container *ngComponentOutlet="componentTypeExpression; 15145 * ngModule: ngModuleClass;"> 15146 * </ng-container> 15147 * ``` 15148 * 15149 * ### A simple example 15150 * 15151 * {@example common/ngComponentOutlet/ts/module.ts region='SimpleExample'} 15152 * 15153 * A more complete example with additional options: 15154 * 15155 * {@example common/ngComponentOutlet/ts/module.ts region='CompleteExample'} 15156 * 15157 * @publicApi 15158 * @ngModule CommonModule 15159 */ 15160 15161 15162class NgComponentOutlet { 15163 constructor(_viewContainerRef) { 15164 this._viewContainerRef = _viewContainerRef; 15165 this.ngComponentOutlet = null; 15166 } 15167 /** @nodoc */ 15168 15169 15170 ngOnChanges(changes) { 15171 const { 15172 _viewContainerRef: viewContainerRef, 15173 ngComponentOutletNgModule: ngModule, 15174 ngComponentOutletNgModuleFactory: ngModuleFactory 15175 } = this; 15176 viewContainerRef.clear(); 15177 this._componentRef = undefined; 15178 15179 if (this.ngComponentOutlet) { 15180 const injector = this.ngComponentOutletInjector || viewContainerRef.parentInjector; 15181
15182 if (changes['ngComponentOutletNgModule'] || changes['ngComponentOutletNgModuleFactory']) { 15183 if (this._moduleRef) this._moduleRef.destroy(); 15184 15185 if (ngModule) { 15186 this._moduleRef = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.createNgModule)(ngModule, getParentInjector(injector)); 15187 } else if (ngModuleFactory) { 15188 this._moduleRef = ngModuleFactory.create(getParentInjector(injector)); 15189 } else { 15190 this._moduleRef = undefined; 15191 } 15192 } 15193 15194 this._componentRef = viewContainerRef.createComponent(this.ngComponentOutlet, { 15195 index: viewContainerRef.length, 15196 injector, 15197 ngModuleRef: this._moduleRef, 15198 projectableNodes: this.ngComponentOutletContent 15199 }); 15200 } 15201 } 15202 /** @nodoc */ 15203 15204 15205 ngOnDestroy() { 15206 if (this._moduleRef) this._moduleRef.destroy(); 15207 } 15208 15209} 15210 15211NgComponentOutlet.ɵfac = function NgComponentOutlet_Factory(t) { 15212 return new (t || NgComponentOutlet)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef)); 15213}; 15214 15215NgComponentOutlet.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 15216 type: NgComponentOutlet, 15217 selectors: [["", "ngComponentOutlet", ""]], 15218 inputs: { 15219 ngComponentOutlet: "ngComponentOutlet", 15220 ngComponentOutletInjector: "ngComponentOutletInjector", 15221 ngComponentOutletContent: "ngComponentOutletContent", 15222 ngComponentOutletNgModule: "ngComponentOutletNgModule", 15223 ngComponentOutletNgModuleFactory: "ngComponentOutletNgModuleFactory" 15224 }, 15225 standalone: true, 15226 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]] 15227}); 15228 15229(function () { 15230 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgComponentOutlet, [{ 15231 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 15232 args: [{ 15233 selector: '[ngComponentOutlet]', 15234 standalone: true 15235 }] 15236 }], function () { 15237 return [{ 15238 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef 15239 }]; 15240 }, { 15241 ngComponentOutlet: [{ 15242 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 15243 }], 15244 ngComponentOutletInjector: [{ 15245 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 15246 }], 15247 ngComponentOutletContent: [{ 15248 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 15249 }], 15250 ngComponentOutletNgModule: [{ 15251 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 15252 }], 15253 ngComponentOutletNgModuleFactory: [{ 15254 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 15255 }] 15256 }); 15257})(); // Helper function that returns an Injector instance of a parent NgModule. 15258 15259 15260function getParentInjector(injector) { 15261 const parentNgModule = injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModuleRef); 15262 return parentNgModule.injector; 15263} 15264/** 15265 * @license 15266 * Copyright Google LLC All Rights Reserved. 15267 * 15268 * Use of this source code is governed by an MIT-style license that can be 15269 * found in the LICENSE file at https://angular.io/license 15270 */ 15271 15272 15273const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode; 15274/** 15275 * @publicApi 15276 */ 15277 15278class NgForOfContext { 15279 constructor($implicit, ngForOf, index, count) { 15280 this.$implicit = $implicit; 15281 this.ngForOf = ngForOf; 15282 this.index = index; 15283 this.count = count; 15284 } 15285 15286 get first() { 15287 return this.index === 0; 15288 } 15289 15290 get last() { 15291 return this.index === this.count - 1; 15292 } 15293 15294 get even() { 15295 return this.index % 2 === 0; 15296 } 15297 15298 get odd() { 15299 return !this.even; 15300 } 15301 15302} 15303/** 15304 * A [structural directive](guide/structural-directives) that renders 15305 * a template for each item in a collection. 15306 * The directive is placed on an element, which becomes the parent 15307 * of the cloned templates. 15308 * 15309 * The `ngForOf` directive is generally used in the 15310 * [shorthand form](guide/structural-directives#asterisk) `*ngFor`. 15311 * In this form, the template to be rendered for each iteration is the content 15312 * of an anchor element containing the directive. 15313 * 15314 * The following example shows the shorthand syntax with some options, 15315 * contained in an `<li>` element. 15316 * 15317 * ``` 15318 * <li *ngFor="let item of items; index as i; trackBy: trackByFn">...</li> 15319 * ``` 15320 * 15321 * The shorthand form expands into a long form that uses the `ngForOf` selector 15322 * on an `<ng-template>` element. 15323 * The content of the `<ng-template>` element is the `<li>` element that held the 15324 * short-form directive. 15325 *
15326 * Here is the expanded version of the short-form example. 15327 * 15328 * ``` 15329 * <ng-template ngFor let-item [ngForOf]="items" let-i="index" [ngForTrackBy]="trackByFn"> 15330 * <li>...</li> 15331 * </ng-template> 15332 * ``` 15333 * 15334 * Angular automatically expands the shorthand syntax as it compiles the template. 15335 * The context for each embedded view is logically merged to the current component 15336 * context according to its lexical position. 15337 * 15338 * When using the shorthand syntax, Angular allows only [one structural directive 15339 * on an element](guide/structural-directives#one-per-element). 15340 * If you want to iterate conditionally, for example, 15341 * put the `*ngIf` on a container element that wraps the `*ngFor` element. 15342 * For further discussion, see 15343 * [Structural Directives](guide/structural-directives#one-per-element). 15344 * 15345 * @usageNotes 15346 * 15347 * ### Local variables 15348 * 15349 * `NgForOf` provides exported values that can be aliased to local variables. 15350 * For example: 15351 * 15352 * ``` 15353 * <li *ngFor="let user of users; index as i; first as isFirst"> 15354 * {{i}}/{{users.length}}. {{user}} <span *ngIf="isFirst">default</span> 15355 * </li> 15356 * ``` 15357 * 15358 * The following exported values can be aliased to local variables: 15359 * 15360 * - `$implicit: T`: The value of the individual items in the iterable (`ngForOf`). 15361 * - `ngForOf: NgIterable<T>`: The value of the iterable expression. Useful when the expression is 15362 * more complex then a property access, for example when using the async pipe (`userStreams | 15363 * async`). 15364 * - `index: number`: The index of the current item in the iterable. 15365 * - `count: number`: The length of the iterable. 15366 * - `first: boolean`: True when the item is the first item in the iterable. 15367 * - `last: boolean`: True when the item is the last item in the iterable. 15368 * - `even: boolean`: True when the item has an even index in the iterable. 15369 * - `odd: boolean`: True when the item has an odd index in the iterable. 15370 * 15371 * ### Change propagation 15372 * 15373 * When the contents of the iterator changes, `NgForOf` makes the corresponding changes to the DOM: 15374 * 15375 * * When an item is added, a new instance of the template is added to the DOM. 15376 * * When an item is removed, its template instance is removed from the DOM. 15377 * * When items are reordered, their respective templates are reordered in the DOM. 15378 * 15379 * Angular uses object identity to track insertions and deletions within the iterator and reproduce 15380 * those changes in the DOM. This has important implications for animations and any stateful 15381 * controls that are present, such as `<input>` elements that accept user input. Inserted rows can 15382 * be animated in, deleted rows can be animated out, and unchanged rows retain any unsaved state 15383 * such as user input. 15384 * For more on animations, see [Transitions and Triggers](guide/transition-and-triggers). 15385 * 15386 * The identities of elements in the iterator can change while the data does not. 15387 * This can happen, for example, if the iterator is produced from an RPC to the server, and that 15388 * RPC is re-run. Even if the data hasn't changed, the second response produces objects with 15389 * different identities, and Angular must tear down the entire DOM and rebuild it (as if all old 15390 * elements were deleted and all new elements inserted). 15391 * 15392 * To avoid this expensive operation, you can customize the default tracking algorithm. 15393 * by supplying the `trackBy` option to `NgForOf`. 15394 * `trackBy` takes a function that has two arguments: `index` and `item`. 15395 * If `trackBy` is given, Angular tracks changes by the return value of the function. 15396 * 15397 * @see [Structural Directives](guide/structural-directives) 15398 * @ngModule CommonModule 15399 * @publicApi 15400 */ 15401 15402 15403class NgForOf { 15404 constructor(_viewContainer, _template, _differs) { 15405 this._viewContainer = _viewContainer; 15406 this._template = _template; 15407 this._differs = _differs; 15408 this._ngForOf = null; 15409 this._ngForOfDirty = true; 15410 this._differ = null; 15411 } 15412 /** 15413 * The value of the iterable expression, which can be used as a 15414 * [template input variable](guide/structural-directives#shorthand). 15415 */ 15416 15417 15418 set ngForOf(ngForOf) { 15419 this._ngForOf = ngForOf; 15420 this._ngForOfDirty = true; 15421 } 15422 /** 15423 * Specifies a custom `TrackByFunction` to compute the identity of items in an iterable. 15424 * 15425 * If a custom `TrackByFunction` is not provided, `NgForOf` will use the item's [object 15426 * identity](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) 15427 * as the key. 15428 * 15429 * `NgForOf` uses the computed key to associate items in an iterable with DOM elements 15430 * it produces for these items. 15431 * 15432 * A custom `TrackByFunction` is useful to provide good user experience in cases when items in an 15433 * iterable rendered using `NgForOf` have a natural identifier (for example, custom ID or a 15434 * primary key), and this iterable could be updated with new object instances that still 15435 * represent the same underlying entity (for example, when data is re-fetched from the server, 15436 * and the iterable is recreated and re-rendered, but most of the data is still the same). 15437 * 15438 * @see `TrackByFunction` 15439 */ 15440 15441 15442 set ngForTrackBy(fn) { 15443 if (NG_DEV_MODE && fn != null && typeof fn !== 'function') { 15444 // TODO(vicb): use a log service once there is a public one available 15445 if (console && console.warn) { 15446 console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}. ` + `See https://angular.io/api/common/NgForOf#change-propagation for more information.`); 15447 } 15448 } 15449 15450 this._trackByFn = fn; 15451 } 15452 15453 get ngForTrackBy() { 15454 return this._trackByFn; 15455 } 15456 /** 15457 * A reference to the template that is stamped out for each item in the iterable. 15458 * @see [template reference variable](guide/template-reference-variables) 15459 */ 15460 15461 15462 set ngForTemplate(value) { 15463 // TODO(TS2.1): make TemplateRef<Partial<NgForRowOf<T>>> once we move to TS v2.1 15464 // The current type is too restrictive; a template that just uses index, for example, 15465 // should be acceptable. 15466 if (value) { 15467 this._template = value; 15468 } 15469 } 15470 /** 15471 * Applies the changes when needed. 15472 * @nodoc 15473 */ 15474 15475 15476 ngDoCheck() { 15477 if (this._ngForOfDirty) { 15478 this._ngForOfDirty = false; // React on ngForOf changes only once all inputs have been initialized 15479 15480 const value = this._ngForOf; 15481 15482 if (!this._differ && value) { 15483 if (NG_DEV_MODE) { 15484 try { 15485 // CAUTION: this logic is duplicated for production mode below, as the try-catch 15486 // is only present in development builds. 15487 this._differ = this._differs.find(value).create(this.ngForTrackBy); 15488 } catch {
15489 let errorMessage = `Cannot find a differ supporting object '${value}' of type '` + `${getTypeName(value)}'. NgFor only supports binding to Iterables, such as Arrays.`; 15490 15491 if (typeof value === 'object') { 15492 errorMessage += ' Did you mean to use the keyvalue pipe?'; 15493 } 15494 15495 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](-2200 15496 /* RuntimeErrorCode.NG_FOR_MISSING_DIFFER */ 15497 , errorMessage); 15498 } 15499 } else { 15500 // CAUTION: this logic is duplicated for development mode above, as the try-catch 15501 // is only present in development builds. 15502 this._differ = this._differs.find(value).create(this.ngForTrackBy); 15503 } 15504 } 15505 } 15506 15507 if (this._differ) { 15508 const changes = this._differ.diff(this._ngForOf); 15509 15510 if (changes) this._applyChanges(changes); 15511 } 15512 } 15513 15514 _applyChanges(changes) { 15515 const viewContainer = this._viewContainer; 15516 changes.forEachOperation((item, adjustedPreviousIndex, currentIndex) => { 15517 if (item.previousIndex == null) { 15518 // NgForOf is never "null" or "undefined" here because the differ detected 15519 // that a new item needs to be inserted from the iterable. This implies that 15520 // there is an iterable value for "_ngForOf". 15521 viewContainer.createEmbeddedView(this._template, new NgForOfContext(item.item, this._ngForOf, -1, -1), currentIndex === null ? undefined : currentIndex); 15522 } else if (currentIndex == null) { 15523 viewContainer.remove(adjustedPreviousIndex === null ? undefined : adjustedPreviousIndex); 15524 } else if (adjustedPreviousIndex !== null) { 15525 const view = viewContainer.get(adjustedPreviousIndex); 15526 viewContainer.move(view, currentIndex); 15527 applyViewChange(view, item); 15528 } 15529 }); 15530 15531 for (let i = 0, ilen = viewContainer.length; i < ilen; i++) { 15532 const viewRef = viewContainer.get(i); 15533 const context = viewRef.context; 15534 context.index = i; 15535 context.count = ilen; 15536 context.ngForOf = this._ngForOf; 15537 } 15538
15539 changes.forEachIdentityChange(record => { 15540 const viewRef = viewContainer.get(record.currentIndex); 15541 applyViewChange(viewRef, record); 15542 }); 15543 } 15544 /** 15545 * Asserts the correct type of the context for the template that `NgForOf` will render. 15546 * 15547 * The presence of this method is a signal to the Ivy template type-check compiler that the 15548 * `NgForOf` structural directive renders its template with a specific context type. 15549 */ 15550 15551 15552 static ngTemplateContextGuard(dir, ctx) { 15553 return true; 15554 } 15555 15556} 15557 15558NgForOf.ɵfac = function NgForOf_Factory(t) { 15559 return new (t || NgForOf)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.TemplateRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.IterableDiffers)); 15560}; 15561 15562NgForOf.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 15563 type: NgForOf, 15564 selectors: [["", "ngFor", "", "ngForOf", ""]], 15565 inputs: { 15566 ngForOf: "ngForOf", 15567 ngForTrackBy: "ngForTrackBy", 15568 ngForTemplate: "ngForTemplate" 15569 }, 15570 standalone: true 15571}); 15572 15573(function () { 15574 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgForOf, [{ 15575 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 15576 args: [{ 15577 selector: '[ngFor][ngForOf]', 15578 standalone: true 15579 }] 15580 }], function () { 15581 return [{ 15582 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef 15583 }, { 15584 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.TemplateRef 15585 }, { 15586 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.IterableDiffers 15587 }]; 15588 }, { 15589 ngForOf: [{ 15590 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 15591 }], 15592 ngForTrackBy: [{ 15593 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 15594 }], 15595 ngForTemplate: [{ 15596 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 15597 }] 15598 }); 15599})(); 15600 15601function applyViewChange(view, record) { 15602 view.context.$implicit = record.item; 15603} 15604 15605function getTypeName(type) { 15606 return type['name'] || typeof type; 15607} 15608/** 15609 * @license 15610 * Copyright Google LLC All Rights Reserved. 15611 * 15612 * Use of this source code is governed by an MIT-style license that can be 15613 * found in the LICENSE file at https://angular.io/license 15614 */ 15615 15616/** 15617 * A structural directive that conditionally includes a template based on the value of 15618 * an expression coerced to Boolean. 15619 * When the expression evaluates to true, Angular renders the template 15620 * provided in a `then` clause, and when false or null, 15621 * Angular renders the template provided in an optional `else` clause. The default 15622 * template for the `else` clause is blank. 15623 * 15624 * A [shorthand form](guide/structural-directives#asterisk) of the directive, 15625 * `*ngIf="condition"`, is generally used, provided 15626 * as an attribute of the anchor element for the inserted template. 15627 * Angular expands this into a more explicit version, in which the anchor element 15628 * is contained in an `<ng-template>` element. 15629 * 15630 * Simple form with shorthand syntax: 15631 * 15632 * ``` 15633 * <div *ngIf="condition">Content to render when condition is true.</div> 15634 * ``` 15635 * 15636 * Simple form with expanded syntax: 15637 * 15638 * ``` 15639 * <ng-template [ngIf]="condition"><div>Content to render when condition is 15640 * true.</div></ng-template> 15641 * ``` 15642 * 15643 * Form with an "else" block: 15644 * 15645 * ``` 15646 * <div *ngIf="condition; else elseBlock">Content to render when condition is true.</div> 15647 * <ng-template #elseBlock>Content to render when condition is false.</ng-template> 15648 * ``` 15649 * 15650 * Shorthand form with "then" and "else" blocks: 15651 * 15652 * ``` 15653 * <div *ngIf="condition; then thenBlock else elseBlock"></div> 15654 * <ng-template #thenBlock>Content to render when condition is true.</ng-template> 15655 * <ng-template #elseBlock>Content to render when condition is false.</ng-template> 15656 * ``` 15657 * 15658 * Form with storing the value locally: 15659 * 15660 * ``` 15661 * <div *ngIf="condition as value; else elseBlock">{{value}}</div> 15662 * <ng-template #elseBlock>Content to render when value is null.</ng-template> 15663 * ``` 15664 * 15665 * @usageNotes 15666 * 15667 * The `*ngIf` directive is most commonly used to conditionally show an inline template, 15668 * as seen in the following example. 15669 * The default `else` template is blank. 15670 * 15671 * {@example common/ngIf/ts/module.ts region='NgIfSimple'} 15672 * 15673 * ### Showing an alternative template using `else` 15674 * 15675 * To display a template when `expression` evaluates to false, use an `else` template 15676 * binding as shown in the following example. 15677 * The `else` binding points to an `<ng-template>` element labeled `#elseBlock`. 15678 * The template can be defined anywhere in the component view, but is typically placed right after 15679 * `ngIf` for readability. 15680 * 15681 * {@example common/ngIf/ts/module.ts region='NgIfElse'} 15682 * 15683 * ### Using an external `then` template 15684 * 15685 * In the previous example, the then-clause template is specified inline, as the content of the 15686 * tag that contains the `ngIf` directive. You can also specify a template that is defined 15687 * externally, by referencing a labeled `<ng-template>` element. When you do this, you can 15688 * change which template to use at runtime, as shown in the following example. 15689 * 15690 * {@example common/ngIf/ts/module.ts region='NgIfThenElse'} 15691 * 15692 * ### Storing a conditional result in a variable 15693 * 15694 * You might want to show a set of properties from the same object. If you are waiting 15695 * for asynchronous data, the object can be undefined. 15696 * In this case, you can use `ngIf` and store the result of the condition in a local 15697 * variable as shown in the following example. 15698 * 15699 * {@example common/ngIf/ts/module.ts region='NgIfAs'} 15700 * 15701 * This code uses only one `AsyncPipe`, so only one subscription is created. 15702 * The conditional statement stores the result of `userStream|async` in the local variable `user`. 15703 * You can then bind the local `user` repeatedly. 15704 * 15705 * The conditional displays the data only if `userStream` returns a value, 15706 * so you don't need to use the 15707 * safe-navigation-operator (`?.`) 15708 * to guard against null values when accessing properties. 15709 * You can display an alternative template while waiting for the data. 15710 * 15711 * ### Shorthand syntax 15712 * 15713 * The shorthand syntax `*ngIf` expands into two separate template specifications 15714 * for the "then" and "else" clauses. For example, consider the following shorthand statement, 15715 * that is meant to show a loading page while waiting for data to be loaded. 15716 * 15717 * ``` 15718 * <div class="hero-list" *ngIf="heroes else loading"> 15719 * ... 15720 * </div> 15721 * 15722 * <ng-template #loading> 15723 * <div>Loading...</div> 15724 * </ng-template> 15725 * ``` 15726 * 15727 * You can see that the "else" clause references the `<ng-template>` 15728 * with the `#loading` label, and the template for the "then" clause
15729 * is provided as the content of the anchor element. 15730 * 15731 * However, when Angular expands the shorthand syntax, it creates 15732 * another `<ng-template>` tag, with `ngIf` and `ngIfElse` directives. 15733 * The anchor element containing the template for the "then" clause becomes 15734 * the content of this unlabeled `<ng-template>` tag. 15735 * 15736 * ``` 15737 * <ng-template [ngIf]="heroes" [ngIfElse]="loading"> 15738 * <div class="hero-list"> 15739 * ... 15740 * </div> 15741 * </ng-template> 15742 * 15743 * <ng-template #loading> 15744 * <div>Loading...</div> 15745 * </ng-template> 15746 * ``` 15747 * 15748 * The presence of the implicit template object has implications for the nesting of 15749 * structural directives. For more on this subject, see 15750 * [Structural Directives](guide/structural-directives#one-per-element). 15751 * 15752 * @ngModule CommonModule 15753 * @publicApi 15754 */ 15755 15756 15757class NgIf { 15758 constructor(_viewContainer, templateRef) { 15759 this._viewContainer = _viewContainer; 15760 this._context = new NgIfContext(); 15761 this._thenTemplateRef = null; 15762 this._elseTemplateRef = null; 15763 this._thenViewRef = null; 15764 this._elseViewRef = null; 15765 this._thenTemplateRef = templateRef; 15766 } 15767 /** 15768 * The Boolean expression to evaluate as the condition for showing a template. 15769 */ 15770 15771 15772 set ngIf(condition) { 15773 this._context.$implicit = this._context.ngIf = condition; 15774 15775 this._updateView(); 15776 } 15777 /** 15778 * A template to show if the condition expression evaluates to true. 15779 */ 15780 15781 15782 set ngIfThen(templateRef) { 15783 assertTemplate('ngIfThen', templateRef); 15784 this._thenTemplateRef = templateRef; 15785 this._thenViewRef = null; // clear previous view if any. 15786 15787 this._updateView(); 15788 } 15789 /** 15790 * A template to show if the condition expression evaluates to false. 15791 */ 15792 15793 15794 set ngIfElse(templateRef) { 15795 assertTemplate('ngIfElse', templateRef); 15796 this._elseTemplateRef = templateRef; 15797 this._elseViewRef = null; // clear previous view if any. 15798 15799 this._updateView(); 15800 } 15801 15802 _updateView() { 15803 if (this._context.$implicit) { 15804 if (!this._thenViewRef) { 15805 this._viewContainer.clear(); 15806 15807 this._elseViewRef = null; 15808 15809 if (this._thenTemplateRef) { 15810 this._thenViewRef = this._viewContainer.createEmbeddedView(this._thenTemplateRef, this._context); 15811 } 15812 } 15813 } else { 15814 if (!this._elseViewRef) { 15815 this._viewContainer.clear(); 15816 15817 this._thenViewRef = null; 15818 15819 if (this._elseTemplateRef) { 15820 this._elseViewRef = this._viewContainer.createEmbeddedView(this._elseTemplateRef, this._context); 15821 } 15822 } 15823 } 15824 } 15825 /** 15826 * Asserts the correct type of the context for the template that `NgIf` will render. 15827 * 15828 * The presence of this method is a signal to the Ivy template type-check compiler that the 15829 * `NgIf` structural directive renders its template with a specific context type. 15830 */ 15831 15832 15833 static ngTemplateContextGuard(dir, ctx) { 15834 return true; 15835 } 15836 15837} 15838 15839NgIf.ɵfac = function NgIf_Factory(t) { 15840 return new (t || NgIf)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.TemplateRef)); 15841}; 15842 15843NgIf.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 15844 type: NgIf, 15845 selectors: [["", "ngIf", ""]], 15846 inputs: { 15847 ngIf: "ngIf",
15848 ngIfThen: "ngIfThen", 15849 ngIfElse: "ngIfElse" 15850 }, 15851 standalone: true 15852}); 15853 15854(function () { 15855 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgIf, [{ 15856 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 15857 args: [{ 15858 selector: '[ngIf]', 15859 standalone: true 15860 }] 15861 }], function () { 15862 return [{ 15863 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef 15864 }, { 15865 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.TemplateRef 15866 }]; 15867 }, { 15868 ngIf: [{ 15869 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 15870 }], 15871 ngIfThen: [{ 15872 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 15873 }], 15874 ngIfElse: [{ 15875 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 15876 }] 15877 }); 15878})(); 15879/** 15880 * @publicApi 15881 */ 15882 15883 15884class NgIfContext { 15885 constructor() { 15886 this.$implicit = null; 15887 this.ngIf = null; 15888 } 15889 15890} 15891 15892function assertTemplate(property, templateRef) { 15893 const isTemplateRefOrNull = !!(!templateRef || templateRef.createEmbeddedView); 15894 15895 if (!isTemplateRefOrNull) { 15896 throw new Error(`${property} must be a TemplateRef, but received '${(0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵstringify"])(templateRef)}'.`); 15897 } 15898} 15899/** 15900 * @license 15901 * Copyright Google LLC All Rights Reserved. 15902 * 15903 * Use of this source code is governed by an MIT-style license that can be 15904 * found in the LICENSE file at https://angular.io/license 15905 */ 15906 15907 15908class SwitchView { 15909 constructor(_viewContainerRef, _templateRef) { 15910 this._viewContainerRef = _viewContainerRef; 15911 this._templateRef = _templateRef; 15912 this._created = false; 15913 } 15914 15915 create() { 15916 this._created = true; 15917 15918 this._viewContainerRef.createEmbeddedView(this._templateRef); 15919 } 15920 15921 destroy() { 15922 this._created = false; 15923 15924 this._viewContainerRef.clear(); 15925 } 15926 15927 enforceState(created) { 15928 if (created && !this._created) { 15929 this.create(); 15930 } else if (!created && this._created) { 15931 this.destroy(); 15932 } 15933 } 15934 15935} 15936/** 15937 * @ngModule CommonModule 15938 * 15939 * @description 15940 * The `[ngSwitch]` directive on a container specifies an expression to match against. 15941 * The expressions to match are provided by `ngSwitchCase` directives on views within the container. 15942 * - Every view that matches is rendered. 15943 * - If there are no matches, a view with the `ngSwitchDefault` directive is rendered. 15944 * - Elements within the `[NgSwitch]` statement but outside of any `NgSwitchCase` 15945 * or `ngSwitchDefault` directive are preserved at the location. 15946 * 15947 * @usageNotes 15948 * Define a container element for the directive, and specify the switch expression 15949 * to match against as an attribute: 15950 * 15951 * ``` 15952 * <container-element [ngSwitch]="switch_expression"> 15953 * ``` 15954 * 15955 * Within the container, `*ngSwitchCase` statements specify the match expressions 15956 * as attributes. Include `*ngSwitchDefault` as the final case. 15957 * 15958 * ``` 15959 * <container-element [ngSwitch]="switch_expression"> 15960 * <some-element *ngSwitchCase="match_expression_1">...</some-element> 15961 * ... 15962 * <some-element *ngSwitchDefault>...</some-element> 15963 * </container-element> 15964 * ``` 15965 * 15966 * ### Usage Examples 15967 * 15968 * The following example shows how to use more than one case to display the same view: 15969 * 15970 * ``` 15971 * <container-element [ngSwitch]="switch_expression"> 15972 * <!-- the same view can be shown in more than one case --> 15973 * <some-element *ngSwitchCase="match_expression_1">...</some-element> 15974 * <some-element *ngSwitchCase="match_expression_2">...</some-element> 15975 * <some-other-element *ngSwitchCase="match_expression_3">...</some-other-element> 15976 * <!--default case when there are no matches --> 15977 * <some-element *ngSwitchDefault>...</some-element> 15978 * </container-element> 15979 * ``` 15980 * 15981 * The following example shows how cases can be nested: 15982 * ``` 15983 * <container-element [ngSwitch]="switch_expression"> 15984 * <some-element *ngSwitchCase="match_expression_1">...</some-element> 15985 * <some-element *ngSwitchCase="match_expression_2">...</some-element> 15986 * <some-other-element *ngSwitchCase="match_expression_3">...</some-other-element> 15987 * <ng-container *ngSwitchCase="match_expression_3"> 15988 * <!-- use a ng-container to group multiple root nodes --> 15989 * <inner-element></inner-element> 15990 * <inner-other-element></inner-other-element> 15991 * </ng-container> 15992 * <some-element *ngSwitchDefault>...</some-element> 15993 * </container-element> 15994 * ``` 15995 * 15996 * @publicApi 15997 * @see `NgSwitchCase` 15998 * @see `NgSwitchDefault` 15999 * @see [Structural Directives](guide/structural-directives) 16000 * 16001 */ 16002 16003 16004class NgSwitch { 16005 constructor() { 16006 this._defaultUsed = false;
16007 this._caseCount = 0; 16008 this._lastCaseCheckIndex = 0; 16009 this._lastCasesMatched = false; 16010 } 16011 16012 set ngSwitch(newValue) { 16013 this._ngSwitch = newValue; 16014 16015 if (this._caseCount === 0) { 16016 this._updateDefaultCases(true); 16017 } 16018 } 16019 /** @internal */ 16020 16021 16022 _addCase() { 16023 return this._caseCount++; 16024 } 16025 /** @internal */ 16026 16027 16028 _addDefault(view) { 16029 if (!this._defaultViews) { 16030 this._defaultViews = []; 16031 } 16032 16033 this._defaultViews.push(view); 16034 } 16035 /** @internal */ 16036 16037 16038 _matchCase(value) { 16039 const matched = value == this._ngSwitch; 16040 this._lastCasesMatched = this._lastCasesMatched || matched; 16041 this._lastCaseCheckIndex++; 16042 16043 if (this._lastCaseCheckIndex === this._caseCount) { 16044 this._updateDefaultCases(!this._lastCasesMatched); 16045 16046 this._lastCaseCheckIndex = 0; 16047 this._lastCasesMatched = false; 16048 } 16049 16050 return matched; 16051 } 16052 16053 _updateDefaultCases(useDefault) { 16054 if (this._defaultViews && useDefault !== this._defaultUsed) { 16055 this._defaultUsed = useDefault; 16056 16057 for (let i = 0; i < this._defaultViews.length; i++) { 16058 const defaultView = this._defaultViews[i]; 16059 defaultView.enforceState(useDefault); 16060 } 16061 } 16062 } 16063 16064} 16065 16066NgSwitch.ɵfac = function NgSwitch_Factory(t) { 16067 return new (t || NgSwitch)(); 16068}; 16069 16070NgSwitch.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 16071 type: NgSwitch, 16072 selectors: [["", "ngSwitch", ""]], 16073 inputs: { 16074 ngSwitch: "ngSwitch" 16075 }, 16076 standalone: true 16077}); 16078 16079(function () { 16080 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgSwitch, [{ 16081 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 16082 args: [{ 16083 selector: '[ngSwitch]', 16084 standalone: true 16085 }] 16086 }], null, { 16087 ngSwitch: [{ 16088 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 16089 }] 16090 }); 16091})(); 16092/** 16093 * @ngModule CommonModule 16094 * 16095 * @description 16096 * Provides a switch case expression to match against an enclosing `ngSwitch` expression. 16097 * When the expressions match, the given `NgSwitchCase` template is rendered. 16098 * If multiple match expressions match the switch expression value, all of them are displayed. 16099 * 16100 * @usageNotes 16101 * 16102 * Within a switch container, `*ngSwitchCase` statements specify the match expressions 16103 * as attributes. Include `*ngSwitchDefault` as the final case. 16104 * 16105 * ``` 16106 * <container-element [ngSwitch]="switch_expression"> 16107 * <some-element *ngSwitchCase="match_expression_1">...</some-element> 16108 * ... 16109 * <some-element *ngSwitchDefault>...</some-element> 16110 * </container-element> 16111 * ``` 16112 * 16113 * Each switch-case statement contains an in-line HTML template or template reference 16114 * that defines the subtree to be selected if the value of the match expression 16115 * matches the value of the switch expression. 16116 * 16117 * Unlike JavaScript, which uses strict equality, Angular uses loose equality. 16118 * This means that the empty string, `""` matches 0. 16119 * 16120 * @publicApi 16121 * @see `NgSwitch` 16122 * @see `NgSwitchDefault` 16123 * 16124 */ 16125 16126 16127class NgSwitchCase { 16128 constructor(viewContainer, templateRef, ngSwitch) { 16129 this.ngSwitch = ngSwitch; 16130 16131 if ((typeof ngDevMode === 'undefined' || ngDevMode) && !ngSwitch) { 16132 throwNgSwitchProviderNotFoundError('ngSwitchCase', 'NgSwitchCase'); 16133 } 16134 16135 ngSwitch._addCase(); 16136 16137 this._view = new SwitchView(viewContainer, templateRef); 16138 } 16139 /** 16140 * Performs case matching. For internal use only. 16141 * @nodoc 16142 */ 16143 16144 16145 ngDoCheck() { 16146 this._view.enforceState(this.ngSwitch._matchCase(this.ngSwitchCase)); 16147 } 16148 16149} 16150 16151NgSwitchCase.ɵfac = function NgSwitchCase_Factory(t) { 16152 return new (t || NgSwitchCase)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.TemplateRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NgSwitch, 9)); 16153}; 16154 16155NgSwitchCase.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 16156 type: NgSwitchCase, 16157 selectors: [["", "ngSwitchCase", ""]], 16158 inputs: { 16159 ngSwitchCase: "ngSwitchCase" 16160 }, 16161 standalone: true 16162}); 16163 16164(function () { 16165 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgSwitchCase, [{ 16166 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 16167 args: [{ 16168 selector: '[ngSwitchCase]', 16169 standalone: true 16170 }] 16171 }], function () { 16172 return [{ 16173 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef 16174 }, {
16175 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.TemplateRef 16176 }, { 16177 type: NgSwitch, 16178 decorators: [{ 16179 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 16180 }, { 16181 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host 16182 }] 16183 }]; 16184 }, { 16185 ngSwitchCase: [{ 16186 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 16187 }] 16188 }); 16189})(); 16190/** 16191 * @ngModule CommonModule 16192 * 16193 * @description 16194 * 16195 * Creates a view that is rendered when no `NgSwitchCase` expressions 16196 * match the `NgSwitch` expression. 16197 * This statement should be the final case in an `NgSwitch`. 16198 * 16199 * @publicApi 16200 * @see `NgSwitch` 16201 * @see `NgSwitchCase` 16202 * 16203 */ 16204 16205 16206class NgSwitchDefault { 16207 constructor(viewContainer, templateRef, ngSwitch) { 16208 if ((typeof ngDevMode === 'undefined' || ngDevMode) && !ngSwitch) { 16209 throwNgSwitchProviderNotFoundError('ngSwitchDefault', 'NgSwitchDefault'); 16210 } 16211 16212 ngSwitch._addDefault(new SwitchView(viewContainer, templateRef)); 16213 } 16214 16215} 16216 16217NgSwitchDefault.ɵfac = function NgSwitchDefault_Factory(t) { 16218 return new (t || NgSwitchDefault)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.TemplateRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NgSwitch, 9)); 16219}; 16220 16221NgSwitchDefault.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 16222 type: NgSwitchDefault, 16223 selectors: [["", "ngSwitchDefault", ""]], 16224 standalone: true 16225}); 16226 16227(function () { 16228 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgSwitchDefault, [{ 16229 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 16230 args: [{ 16231 selector: '[ngSwitchDefault]', 16232 standalone: true 16233 }] 16234 }], function () { 16235 return [{ 16236 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef 16237 }, { 16238 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.TemplateRef 16239 }, { 16240 type: NgSwitch, 16241 decorators: [{ 16242 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 16243 }, { 16244 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host 16245 }] 16246 }]; 16247 }, null); 16248})(); 16249 16250function throwNgSwitchProviderNotFoundError(attrName, directiveName) { 16251 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2000 16252 /* RuntimeErrorCode.PARENT_NG_SWITCH_NOT_FOUND */ 16253 , `An element with the "${attrName}" attribute ` + `(matching the "${directiveName}" directive) must be located inside an element with the "ngSwitch" attribute ` + `(matching "NgSwitch" directive)`); 16254} 16255/** 16256 * @license 16257 * Copyright Google LLC All Rights Reserved. 16258 * 16259 * Use of this source code is governed by an MIT-style license that can be 16260 * found in the LICENSE file at https://angular.io/license 16261 */ 16262 16263/** 16264 * @ngModule CommonModule 16265 * 16266 * @usageNotes 16267 * ``` 16268 * <some-element [ngPlural]="value"> 16269 * <ng-template ngPluralCase="=0">there is nothing</ng-template> 16270 * <ng-template ngPluralCase="=1">there is one</ng-template> 16271 * <ng-template ngPluralCase="few">there are a few</ng-template> 16272 * </some-element> 16273 * ``` 16274 * 16275 * @description 16276 * 16277 * Adds / removes DOM sub-trees based on a numeric value. Tailored for pluralization. 16278 * 16279 * Displays DOM sub-trees that match the switch expression value, or failing that, DOM sub-trees 16280 * that match the switch expression's pluralization category. 16281 * 16282 * To use this directive you must provide a container element that sets the `[ngPlural]` attribute 16283 * to a switch expression. Inner elements with a `[ngPluralCase]` will display based on their 16284 * expression: 16285 * - if `[ngPluralCase]` is set to a value starting with `=`, it will only display if the value 16286 * matches the switch expression exactly, 16287 * - otherwise, the view will be treated as a "category match", and will only display if exact 16288 * value matches aren't found and the value maps to its category for the defined locale. 16289 * 16290 * See http://cldr.unicode.org/index/cldr-spec/plural-rules 16291 * 16292 * @publicApi 16293 */ 16294 16295 16296class NgPlural { 16297 constructor(_localization) { 16298 this._localization = _localization; 16299 this._caseViews = {}; 16300 } 16301 16302 set ngPlural(value) { 16303 this._switchValue = value; 16304 16305 this._updateView(); 16306 } 16307 16308 addCase(value, switchView) { 16309 this._caseViews[value] = switchView; 16310 } 16311 16312 _updateView() { 16313 this._clearViews(); 16314 16315 const cases = Object.keys(this._caseViews);
16316 const key = getPluralCategory(this._switchValue, cases, this._localization); 16317 16318 this._activateView(this._caseViews[key]); 16319 } 16320 16321 _clearViews() { 16322 if (this._activeView) this._activeView.destroy(); 16323 } 16324 16325 _activateView(view) { 16326 if (view) { 16327 this._activeView = view; 16328 16329 this._activeView.create(); 16330 } 16331 } 16332 16333} 16334 16335NgPlural.ɵfac = function NgPlural_Factory(t) { 16336 return new (t || NgPlural)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NgLocalization)); 16337}; 16338 16339NgPlural.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 16340 type: NgPlural, 16341 selectors: [["", "ngPlural", ""]], 16342 inputs: { 16343 ngPlural: "ngPlural" 16344 }, 16345 standalone: true 16346}); 16347 16348(function () { 16349 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgPlural, [{ 16350 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 16351 args: [{ 16352 selector: '[ngPlural]', 16353 standalone: true 16354 }] 16355 }], function () { 16356 return [{ 16357 type: NgLocalization 16358 }]; 16359 }, { 16360 ngPlural: [{ 16361 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 16362 }] 16363 }); 16364})(); 16365/** 16366 * @ngModule CommonModule 16367 * 16368 * @description 16369 * 16370 * Creates a view that will be added/removed from the parent {@link NgPlural} when the 16371 * given expression matches the plural expression according to CLDR rules. 16372 * 16373 * @usageNotes 16374 * ``` 16375 * <some-element [ngPlural]="value"> 16376 * <ng-template ngPluralCase="=0">...</ng-template> 16377 * <ng-template ngPluralCase="other">...</ng-template> 16378 * </some-element> 16379 *``` 16380 * 16381 * See {@link NgPlural} for more details and example. 16382 * 16383 * @publicApi 16384 */ 16385 16386 16387class NgPluralCase { 16388 constructor(value, template, viewContainer, ngPlural) { 16389 this.value = value; 16390 const isANumber = !isNaN(Number(value)); 16391 ngPlural.addCase(isANumber ? `=${value}` : value, new SwitchView(viewContainer, template)); 16392 } 16393 16394} 16395 16396NgPluralCase.ɵfac = function NgPluralCase_Factory(t) { 16397 return new (t || NgPluralCase)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinjectAttribute"]('ngPluralCase'), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.TemplateRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NgPlural, 1)); 16398}; 16399 16400NgPluralCase.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 16401 type: NgPluralCase, 16402 selectors: [["", "ngPluralCase", ""]], 16403 standalone: true 16404}); 16405 16406(function () { 16407 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgPluralCase, [{ 16408 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 16409 args: [{ 16410 selector: '[ngPluralCase]', 16411 standalone: true 16412 }] 16413 }], function () { 16414 return [{ 16415 type: undefined, 16416 decorators: [{ 16417 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Attribute, 16418 args: ['ngPluralCase'] 16419 }] 16420 }, { 16421 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.TemplateRef 16422 }, { 16423 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef 16424 }, { 16425 type: NgPlural, 16426 decorators: [{ 16427 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host 16428 }] 16429 }]; 16430 }, null); 16431})(); 16432/** 16433 * @license 16434 * Copyright Google LLC All Rights Reserved. 16435 * 16436 * Use of this source code is governed by an MIT-style license that can be 16437 * found in the LICENSE file at https://angular.io/license 16438 */ 16439 16440/** 16441 * @ngModule CommonModule 16442 * 16443 * @usageNotes 16444 * 16445 * Set the font of the containing element to the result of an expression. 16446 * 16447 * ``` 16448 * <some-element [ngStyle]="{'font-style': styleExp}">...</some-element> 16449 * ``` 16450 * 16451 * Set the width of the containing element to a pixel value returned by an expression. 16452 * 16453 * ``` 16454 * <some-element [ngStyle]="{'max-width.px': widthExp}">...</some-element> 16455 * ``` 16456 * 16457 * Set a collection of style values using an expression that returns key-value pairs. 16458 * 16459 * ``` 16460 * <some-element [ngStyle]="objExp">...</some-element> 16461 * ``` 16462 * 16463 * @description 16464 * 16465 * An attribute directive that updates styles for the containing HTML element. 16466 * Sets one or more style properties, specified as colon-separated key-value pairs. 16467 * The key is a style name, with an optional `.<unit>` suffix 16468 * (such as 'top.px', 'font-style.em'). 16469 * The value is an expression to be evaluated. 16470 * The resulting non-null value, expressed in the given unit, 16471 * is assigned to the given style property. 16472 * If the result of evaluation is null, the corresponding style is removed. 16473 * 16474 * @publicApi 16475 */ 16476 16477 16478class NgStyle { 16479 constructor(_ngEl, _differs, _renderer) { 16480 this._ngEl = _ngEl; 16481 this._differs = _differs; 16482 this._renderer = _renderer; 16483 this._ngStyle = null; 16484 this._differ = null; 16485 } 16486 16487 set ngStyle(values) { 16488 this._ngStyle = values; 16489 16490 if (!this._differ && values) { 16491 this._differ = this._differs.find(values).create(); 16492 } 16493 } 16494 16495 ngDoCheck() { 16496 if (this._differ) { 16497 const changes = this._differ.diff(this._ngStyle); 16498 16499 if (changes) { 16500 this._applyChanges(changes); 16501 } 16502 } 16503 } 16504 16505 _setStyle(nameAndUnit, value) { 16506 const [name, unit] = nameAndUnit.split('.'); 16507 const flags = name.indexOf('-') === -1 ? undefined : _angular_core__WEBPACK_IMPORTED_MODULE_0__.RendererStyleFlags2.DashCase; 16508 16509 if (value != null) { 16510 this._renderer.setStyle(this._ngEl.nativeElement, name, unit ? `${value}${unit}` : value, flags); 16511 } else { 16512 this._renderer.removeStyle(this._ngEl.nativeElement, name, flags); 16513 } 16514 } 16515 16516 _applyChanges(changes) {
16517 changes.forEachRemovedItem(record => this._setStyle(record.key, null)); 16518 changes.forEachAddedItem(record => this._setStyle(record.key, record.currentValue)); 16519 changes.forEachChangedItem(record => this._setStyle(record.key, record.currentValue)); 16520 } 16521 16522} 16523 16524NgStyle.ɵfac = function NgStyle_Factory(t) { 16525 return new (t || NgStyle)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.KeyValueDiffers), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2)); 16526}; 16527 16528NgStyle.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 16529 type: NgStyle, 16530 selectors: [["", "ngStyle", ""]], 16531 inputs: { 16532 ngStyle: "ngStyle" 16533 }, 16534 standalone: true 16535}); 16536 16537(function () { 16538 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgStyle, [{ 16539 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 16540 args: [{ 16541 selector: '[ngStyle]', 16542 standalone: true 16543 }] 16544 }], function () { 16545 return [{ 16546 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef 16547 }, { 16548 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.KeyValueDiffers 16549 }, { 16550 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2 16551 }]; 16552 }, { 16553 ngStyle: [{ 16554 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 16555 args: ['ngStyle'] 16556 }] 16557 }); 16558})(); 16559/** 16560 * @license 16561 * Copyright Google LLC All Rights Reserved. 16562 * 16563 * Use of this source code is governed by an MIT-style license that can be 16564 * found in the LICENSE file at https://angular.io/license 16565 */ 16566 16567/** 16568 * @ngModule CommonModule 16569 * 16570 * @description 16571 * 16572 * Inserts an embedded view from a prepared `TemplateRef`. 16573 * 16574 * You can attach a context object to the `EmbeddedViewRef` by setting `[ngTemplateOutletContext]`. 16575 * `[ngTemplateOutletContext]` should be an object, the object's keys will be available for binding 16576 * by the local template `let` declarations. 16577 * 16578 * @usageNotes 16579 * ``` 16580 * <ng-container *ngTemplateOutlet="templateRefExp; context: contextExp"></ng-container> 16581 * ``` 16582 * 16583 * Using the key `$implicit` in the context object will set its value as default. 16584 * 16585 * ### Example 16586 * 16587 * {@example common/ngTemplateOutlet/ts/module.ts region='NgTemplateOutlet'} 16588 * 16589 * @publicApi 16590 */ 16591 16592 16593class NgTemplateOutlet { 16594 constructor(_viewContainerRef) { 16595 this._viewContainerRef = _viewContainerRef; 16596 this._viewRef = null; 16597 /** 16598 * A context object to attach to the {@link EmbeddedViewRef}. This should be an 16599 * object, the object's keys will be available for binding by the local template `let` 16600 * declarations. 16601 * Using the key `$implicit` in the context object will set its value as default. 16602 */ 16603 16604 this.ngTemplateOutletContext = null; 16605 /** 16606 * A string defining the template reference and optionally the context object for the template. 16607 */ 16608 16609 this.ngTemplateOutlet = null; 16610 /** Injector to be used within the embedded view. */ 16611 16612 this.ngTemplateOutletInjector = null; 16613 } 16614 /** @nodoc */ 16615 16616 16617 ngOnChanges(changes) { 16618 if (changes['ngTemplateOutlet'] || changes['ngTemplateOutletInjector']) { 16619 const viewContainerRef = this._viewContainerRef; 16620 16621 if (this._viewRef) { 16622 viewContainerRef.remove(viewContainerRef.indexOf(this._viewRef)); 16623 } 16624 16625 if (this.ngTemplateOutlet) { 16626 const { 16627 ngTemplateOutlet: template, 16628 ngTemplateOutletContext: context, 16629 ngTemplateOutletInjector: injector 16630 } = this; 16631 this._viewRef = viewContainerRef.createEmbeddedView(template, context, injector ? { 16632 injector 16633 } : undefined); 16634 } else { 16635 this._viewRef = null; 16636 } 16637 } else if (this._viewRef && changes['ngTemplateOutletContext'] && this.ngTemplateOutletContext) { 16638 this._viewRef.context = this.ngTemplateOutletContext; 16639 } 16640 } 16641 16642} 16643 16644NgTemplateOutlet.ɵfac = function NgTemplateOutlet_Factory(t) { 16645 return new (t || NgTemplateOutlet)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef)); 16646}; 16647 16648NgTemplateOutlet.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 16649 type: NgTemplateOutlet, 16650 selectors: [["", "ngTemplateOutlet", ""]], 16651 inputs: { 16652 ngTemplateOutletContext: "ngTemplateOutletContext", 16653 ngTemplateOutlet: "ngTemplateOutlet", 16654 ngTemplateOutletInjector: "ngTemplateOutletInjector" 16655 }, 16656 standalone: true, 16657 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]] 16658}); 16659 16660(function () { 16661 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgTemplateOutlet, [{ 16662 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 16663 args: [{ 16664 selector: '[ngTemplateOutlet]', 16665 standalone: true 16666 }] 16667 }], function () { 16668 return [{ 16669 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef 16670 }]; 16671 }, { 16672 ngTemplateOutletContext: [{ 16673 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 16674 }], 16675 ngTemplateOutlet: [{ 16676 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 16677 }], 16678 ngTemplateOutletInjector: [{ 16679 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 16680 }] 16681 }); 16682})(); 16683/** 16684 * @license 16685 * Copyright Google LLC All Rights Reserved. 16686 * 16687 * Use of this source code is governed by an MIT-style license that can be 16688 * found in the LICENSE file at https://angular.io/license 16689 */ 16690 16691/** 16692 * A collection of Angular directives that are likely to be used in each and every Angular 16693 * application. 16694 */ 16695 16696 16697const COMMON_DIRECTIVES = [NgClass, NgComponentOutlet, NgForOf, NgIf, NgTemplateOutlet, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgPlural, NgPluralCase]; 16698/** 16699 * @license 16700 * Copyright Google LLC All Rights Reserved. 16701 * 16702 * Use of this source code is governed by an MIT-style license that can be 16703 * found in the LICENSE file at https://angular.io/license 16704 */ 16705
16706function invalidPipeArgumentError(type, value) { 16707 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2100 16708 /* RuntimeErrorCode.INVALID_PIPE_ARGUMENT */ 16709 , ngDevMode && `InvalidPipeArgument: '${value}' for pipe '${(0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵstringify"])(type)}'`); 16710} 16711/** 16712 * @license 16713 * Copyright Google LLC All Rights Reserved. 16714 * 16715 * Use of this source code is governed by an MIT-style license that can be 16716 * found in the LICENSE file at https://angular.io/license 16717 */ 16718 16719 16720class SubscribableStrategy { 16721 createSubscription(async, updateLatestValue) { 16722 return async.subscribe({ 16723 next: updateLatestValue, 16724 error: e => { 16725 throw e; 16726 } 16727 }); 16728 } 16729 16730 dispose(subscription) { 16731 subscription.unsubscribe(); 16732 } 16733 16734} 16735 16736class PromiseStrategy { 16737 createSubscription(async, updateLatestValue) { 16738 return async.then(updateLatestValue, e => { 16739 throw e; 16740 }); 16741 } 16742 16743 dispose(subscription) {} 16744 16745} 16746 16747const _promiseStrategy = new PromiseStrategy(); 16748 16749const _subscribableStrategy = new SubscribableStrategy(); 16750/** 16751 * @ngModule CommonModule 16752 * @description 16753 * 16754 * Unwraps a value from an asynchronous primitive. 16755 * 16756 * The `async` pipe subscribes to an `Observable` or `Promise` and returns the latest value it has 16757 * emitted. When a new value is emitted, the `async` pipe marks the component to be checked for 16758 * changes. When the component gets destroyed, the `async` pipe unsubscribes automatically to avoid 16759 * potential memory leaks. When the reference of the expression changes, the `async` pipe 16760 * automatically unsubscribes from the old `Observable` or `Promise` and subscribes to the new one. 16761 * 16762 * @usageNotes 16763 * 16764 * ### Examples 16765 * 16766 * This example binds a `Promise` to the view. Clicking the `Resolve` button resolves the 16767 * promise. 16768 * 16769 * {@example common/pipes/ts/async_pipe.ts region='AsyncPipePromise'} 16770 * 16771 * It's also possible to use `async` with Observables. The example below binds the `time` Observable 16772 * to the view. The Observable continuously updates the view with the current time. 16773 * 16774 * {@example common/pipes/ts/async_pipe.ts region='AsyncPipeObservable'} 16775 * 16776 * @publicApi 16777 */ 16778 16779 16780class AsyncPipe { 16781 constructor(ref) { 16782 this._latestValue = null; 16783 this._subscription = null; 16784 this._obj = null; 16785 this._strategy = null; // Assign `ref` into `this._ref` manually instead of declaring `_ref` in the constructor 16786 // parameter list, as the type of `this._ref` includes `null` unlike the type of `ref`. 16787 16788 this._ref = ref; 16789 } 16790 16791 ngOnDestroy() { 16792 if (this._subscription) { 16793 this._dispose(); 16794 } // Clear the `ChangeDetectorRef` and its association with the view data, to mitigate 16795 // potential memory leaks in Observables that could otherwise cause the view data to 16796 // be retained. 16797 // https://github.com/angular/angular/issues/17624 16798 16799 16800 this._ref = null; 16801 } 16802 16803 transform(obj) { 16804 if (!this._obj) { 16805 if (obj) { 16806 this._subscribe(obj); 16807 } 16808 16809 return this._latestValue; 16810 } 16811 16812 if (obj !== this._obj) { 16813 this._dispose(); 16814 16815 return this.transform(obj); 16816 } 16817 16818 return this._latestValue; 16819 } 16820 16821 _subscribe(obj) { 16822 this._obj = obj; 16823 this._strategy = this._selectStrategy(obj); 16824 this._subscription = this._strategy.createSubscription(obj, value => this._updateLatestValue(obj, value)); 16825 } 16826 16827 _selectStrategy(obj) { 16828 if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisPromise"])(obj)) { 16829 return _promiseStrategy; 16830 } 16831 16832 if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisSubscribable"])(obj)) { 16833 return _subscribableStrategy; 16834 } 16835 16836 throw invalidPipeArgumentError(AsyncPipe, obj); 16837 } 16838 16839 _dispose() {
16840 // Note: `dispose` is only called if a subscription has been initialized before, indicating 16841 // that `this._strategy` is also available. 16842 this._strategy.dispose(this._subscription); 16843 16844 this._latestValue = null; 16845 this._subscription = null; 16846 this._obj = null; 16847 } 16848 16849 _updateLatestValue(async, value) { 16850 if (async === this._obj) { 16851 this._latestValue = value; // Note: `this._ref` is only cleared in `ngOnDestroy` so is known to be available when a 16852 // value is being updated. 16853 16854 this._ref.markForCheck(); 16855 } 16856 } 16857 16858} 16859 16860AsyncPipe.ɵfac = function AsyncPipe_Factory(t) { 16861 return new (t || AsyncPipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef, 16)); 16862}; 16863 16864AsyncPipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ 16865 name: "async", 16866 type: AsyncPipe, 16867 pure: false, 16868 standalone: true 16869}); 16870 16871(function () { 16872 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](AsyncPipe, [{ 16873 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe, 16874 args: [{ 16875 name: 'async', 16876 pure: false, 16877 standalone: true 16878 }] 16879 }], function () { 16880 return [{ 16881 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef 16882 }]; 16883 }, null); 16884})(); 16885/** 16886 * @license 16887 * Copyright Google LLC All Rights Reserved. 16888 * 16889 * Use of this source code is governed by an MIT-style license that can be 16890 * found in the LICENSE file at https://angular.io/license 16891 */ 16892 16893/** 16894 * Transforms text to all lower case. 16895 * 16896 * @see `UpperCasePipe` 16897 * @see `TitleCasePipe` 16898 * @usageNotes 16899 * 16900 * The following example defines a view that allows the user to enter 16901 * text, and then uses the pipe to convert the input text to all lower case. 16902 * 16903 * <code-example path="common/pipes/ts/lowerupper_pipe.ts" region='LowerUpperPipe'></code-example> 16904 * 16905 * @ngModule CommonModule 16906 * @publicApi 16907 */ 16908 16909 16910class LowerCasePipe { 16911 transform(value) { 16912 if (value == null) return null; 16913 16914 if (typeof value !== 'string') { 16915 throw invalidPipeArgumentError(LowerCasePipe, value); 16916 } 16917 16918 return value.toLowerCase(); 16919 } 16920 16921} 16922 16923LowerCasePipe.ɵfac = function LowerCasePipe_Factory(t) { 16924 return new (t || LowerCasePipe)(); 16925}; 16926 16927LowerCasePipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ 16928 name: "lowercase", 16929 type: LowerCasePipe, 16930 pure: true, 16931 standalone: true 16932}); 16933 16934(function () { 16935 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](LowerCasePipe, [{ 16936 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe, 16937 args: [{ 16938 name: 'lowercase', 16939 standalone: true 16940 }] 16941 }], null, null); 16942})(); // 16943// Regex below matches any Unicode word and number compatible with ES5. In ES2018 the same result 16944// can be achieved by using /[0-9\p{L}]\S*/gu and also known as Unicode Property Escapes 16945// (https://2ality.com/2017/07/regexp-unicode-property-escapes.html). Since there is no 16946// transpilation of this functionality down to ES5 without external tool, the only solution is 16947// to use already transpiled form. Example can be found here - 16948// https://mothereff.in/regexpu#input=var+regex+%3D+%2F%5B0-9%5Cp%7BL%7D%5D%5CS*%2Fgu%3B%0A%0A&unicodePropertyEscape=1 16949// 16950 16951 16952const unicodeWordMatch = /(?:[0-9A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088E\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5D\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u
169520EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDF70-\uDF81\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC71\uDC72\uDC75\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDEB8\uDF00-\uDF1A\uDF40-\uDF46]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCDF\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEB0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE70-\uDEBE\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD837[\uDF00-\uDF1E]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB]|\uD839[\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF38\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])\S*/g; 16953/** 16954 * Transforms text to title case. 16955 * Capitalizes the first letter of each word and transforms the 16956 * rest of the word to lower case. 16957 * Words are delimited by any whitespace character, such as a space, tab, or line-feed character. 16958 * 16959 * @see `LowerCasePipe` 16960 * @see `UpperCasePipe` 16961 * 16962 * @usageNotes 16963 * The following example shows the result of transforming various strings into title case. 16964 * 16965 * <code-example path="common/pipes/ts/titlecase_pipe.ts" region='TitleCasePipe'></code-example> 16966 * 16967 * @ngModule CommonModule 16968 * @publicApi 16969 */ 16970 16971class TitleCasePipe { 16972 transform(value) { 16973 if (value == null) return null; 16974 16975 if (typeof value !== 'string') {
16976 throw invalidPipeArgumentError(TitleCasePipe, value); 16977 } 16978 16979 return value.replace(unicodeWordMatch, txt => txt[0].toUpperCase() + txt.slice(1).toLowerCase()); 16980 } 16981 16982} 16983 16984TitleCasePipe.ɵfac = function TitleCasePipe_Factory(t) { 16985 return new (t || TitleCasePipe)(); 16986}; 16987 16988TitleCasePipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ 16989 name: "titlecase", 16990 type: TitleCasePipe, 16991 pure: true, 16992 standalone: true 16993}); 16994 16995(function () { 16996 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](TitleCasePipe, [{ 16997 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe, 16998 args: [{ 16999 name: 'titlecase', 17000 standalone: true 17001 }] 17002 }], null, null); 17003})(); 17004/** 17005 * Transforms text to all upper case. 17006 * @see `LowerCasePipe` 17007 * @see `TitleCasePipe` 17008 * 17009 * @ngModule CommonModule 17010 * @publicApi 17011 */ 17012 17013 17014class UpperCasePipe { 17015 transform(value) { 17016 if (value == null) return null; 17017 17018 if (typeof value !== 'string') { 17019 throw invalidPipeArgumentError(UpperCasePipe, value); 17020 } 17021 17022 return value.toUpperCase(); 17023 } 17024 17025} 17026 17027UpperCasePipe.ɵfac = function UpperCasePipe_Factory(t) { 17028 return new (t || UpperCasePipe)(); 17029}; 17030 17031UpperCasePipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ 17032 name: "uppercase", 17033 type: UpperCasePipe, 17034 pure: true, 17035 standalone: true 17036}); 17037 17038(function () { 17039 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](UpperCasePipe, [{ 17040 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe, 17041 args: [{ 17042 name: 'uppercase', 17043 standalone: true 17044 }] 17045 }], null, null); 17046})(); 17047/** 17048 * @license 17049 * Copyright Google LLC All Rights Reserved. 17050 * 17051 * Use of this source code is governed by an MIT-style license that can be 17052 * found in the LICENSE file at https://angular.io/license 17053 */ 17054 17055/** 17056 * Optionally-provided default timezone to use for all instances of `DatePipe` (such as `'+0430'`). 17057 * If the value isn't provided, the `DatePipe` will use the end-user's local system timezone. 17058 */ 17059 17060 17061const DATE_PIPE_DEFAULT_TIMEZONE = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('DATE_PIPE_DEFAULT_TIMEZONE'); // clang-format off 17062 17063/** 17064 * @ngModule CommonModule 17065 * @description 17066 * 17067 * Formats a date value according to locale rules. 17068 * 17069 * `DatePipe` is executed only when it detects a pure change to the input value. 17070 * A pure change is either a change to a primitive input value 17071 * (such as `String`, `Number`, `Boolean`, or `Symbol`), 17072 * or a changed object reference (such as `Date`, `Array`, `Function`, or `Object`). 17073 * 17074 * Note that mutating a `Date` object does not cause the pipe to be rendered again. 17075 * To ensure that the pipe is executed, you must create a new `Date` object. 17076 * 17077 * Only the `en-US` locale data comes with Angular. To localize dates 17078 * in another language, you must import the corresponding locale data. 17079 * See the [I18n guide](guide/i18n-common-format-data-locale) for more information. 17080 * 17081 * The time zone of the formatted value can be specified either by passing it in as the second 17082 * parameter of the pipe, or by setting the default through the `DATE_PIPE_DEFAULT_TIMEZONE` 17083 * injection token. The value that is passed in as the second parameter takes precedence over 17084 * the one defined using the injection token. 17085 * 17086 * @see `formatDate()` 17087 * 17088 * 17089 * @usageNotes 17090 * 17091 * The result of this pipe is not reevaluated when the input is mutated. To avoid the need to 17092 * reformat the date on every change-detection cycle, treat the date as an immutable object 17093 * and change the reference when the pipe needs to run again. 17094 * 17095 * ### Pre-defined format options 17096 * 17097 * | Option | Equivalent to | Examples (given in `en-US` locale) | 17098 * |---------------|-------------------------------------|-------------------------------------------------| 17099 * | `'short'` | `'M/d/yy, h:mm a'` | `6/15/15, 9:03 AM` | 17100 * | `'medium'` | `'MMM d, y, h:mm:ss a'` | `Jun 15, 2015, 9:03:01 AM` | 17101 * | `'long'` | `'MMMM d, y, h:mm:ss a z'` | `June 15, 2015 at 9:03:01 AM GMT+1` | 17102 * | `'full'` | `'EEEE, MMMM d, y, h:mm:ss a zzzz'` | `Monday, June 15, 2015 at 9:03:01 AM GMT+01:00` | 17103 * | `'shortDate'` | `'M/d/yy'` | `6/15/15` | 17104 * | `'mediumDate'`| `'MMM d, y'` | `Jun 15, 2015` | 17105 * | `'longDate'` | `'MMMM d, y'` | `June 15, 2015` | 17106 * | `'fullDate'` | `'EEEE, MMMM d, y'` | `Monday, June 15, 2015` | 17107 * | `'shortTime'` | `'h:mm a'` | `9:03 AM` | 17108 * | `'mediumTime'`| `'h:mm:ss a'` | `9:03:01 AM` | 17109 * | `'longTime'` | `'h:mm:ss a z'` | `9:03:01 AM GMT+1` | 17110 * | `'fullTime'` | `'h:mm:ss a zzzz'` | `9:03:01 AM GMT+01:00` | 17111 * 17112 * ### Custom format options 17113 *
17114 * You can construct a format string using symbols to specify the components 17115 * of a date-time value, as described in the following table. 17116 * Format details depend on the locale. 17117 * Fields marked with (*) are only available in the extra data set for the given locale. 17118 * 17119 * | Field type | Format | Description | Example Value | 17120 * |-------------------- |-------------|---------------------------------------------------------------|------------------------------------------------------------| 17121 * | Era | G, GG & GGG | Abbreviated | AD | 17122 * | | GGGG | Wide | Anno Domini | 17123 * | | GGGGG | Narrow | A | 17124 * | Year | y | Numeric: minimum digits | 2, 20, 201, 2017, 20173 | 17125 * | | yy | Numeric: 2 digits + zero padded | 02, 20, 01, 17, 73 | 17126 * | | yyy | Numeric: 3 digits + zero padded | 002, 020, 201, 2017, 20173 | 17127 * | | yyyy | Numeric: 4 digits or more + zero padded | 0002, 0020, 0201, 2017, 20173 | 17128 * | Week-numbering year | Y | Numeric: minimum digits | 2, 20, 201, 2017, 20173 | 17129 * | | YY | Numeric: 2 digits + zero padded | 02, 20, 01, 17, 73 | 17130 * | | YYY | Numeric: 3 digits + zero padded | 002, 020, 201, 2017, 20173 | 17131 * | | YYYY | Numeric: 4 digits or more + zero padded | 0002, 0020, 0201, 2017, 20173 | 17132 * | Month | M | Numeric: 1 digit | 9, 12 | 17133 * | | MM | Numeric: 2 digits + zero padded | 09, 12 | 17134 * | | MMM | Abbreviated | Sep | 17135 * | | MMMM | Wide | September | 17136 * | | MMMMM | Narrow | S | 17137 * | Month standalone | L | Numeric: 1 digit | 9, 12 | 17138 * | | LL | Numeric: 2 digits + zero padded | 09, 12 | 17139 * | | LLL | Abbreviated | Sep | 17140 * | | LLLL | Wide | September | 17141 * | | LLLLL | Narrow | S | 17142 * | Week of year | w | Numeric: minimum digits | 1... 53 | 17143 * | | ww | Numeric: 2 digits + zero padded | 01... 53 | 17144 * | Week of month | W | Numeric: 1 digit | 1... 5 | 17145 * | Day of month | d | Numeric: minimum digits | 1 | 17146 * | | dd | Numeric: 2 digits + zero padded | 01 | 17147 * | Week day | E, EE & EEE | Abbreviated | Tue | 17148 * | | EEEE | Wide | Tuesday | 17149 * | | EEEEE | Narrow | T | 17150 * | | EEEEEE | Short | Tu | 17151 * | Week day standalone | c, cc | Numeric: 1 digit | 2 | 17152 * | | ccc | Abbreviated | Tue | 17153 * | | cccc | Wide | Tuesday | 17154 * | | ccccc | Narrow | T | 17155 * | | cccccc | Short | Tu |
17156 * | Period | a, aa & aaa | Abbreviated | am/pm or AM/PM | 17157 * | | aaaa | Wide (fallback to `a` when missing) | ante meridiem/post meridiem | 17158 * | | aaaaa | Narrow | a/p | 17159 * | Period* | B, BB & BBB | Abbreviated | mid. | 17160 * | | BBBB | Wide | am, pm, midnight, noon, morning, afternoon, evening, night | 17161 * | | BBBBB | Narrow | md | 17162 * | Period standalone* | b, bb & bbb | Abbreviated | mid. | 17163 * | | bbbb | Wide | am, pm, midnight, noon, morning, afternoon, evening, night | 17164 * | | bbbbb | Narrow | md | 17165 * | Hour 1-12 | h | Numeric: minimum digits | 1, 12 | 17166 * | | hh | Numeric: 2 digits + zero padded | 01, 12 | 17167 * | Hour 0-23 | H | Numeric: minimum digits | 0, 23 | 17168 * | | HH | Numeric: 2 digits + zero padded | 00, 23 | 17169 * | Minute | m | Numeric: minimum digits | 8, 59 | 17170 * | | mm | Numeric: 2 digits + zero padded | 08, 59 | 17171 * | Second | s | Numeric: minimum digits | 0... 59 | 17172 * | | ss | Numeric: 2 digits + zero padded | 00... 59 | 17173 * | Fractional seconds | S | Numeric: 1 digit | 0... 9 | 17174 * | | SS | Numeric: 2 digits + zero padded | 00... 99 | 17175 * | | SSS | Numeric: 3 digits + zero padded (= milliseconds) | 000... 999 | 17176 * | Zone | z, zz & zzz | Short specific non location format (fallback to O) | GMT-8 | 17177 * | | zzzz | Long specific non location format (fallback to OOOO) | GMT-08:00 | 17178 * | | Z, ZZ & ZZZ | ISO8601 basic format | -0800 | 17179 * | | ZZZZ | Long localized GMT format | GMT-8:00 | 17180 * | | ZZZZZ | ISO8601 extended format + Z indicator for offset 0 (= XXXXX) | -08:00 | 17181 * | | O, OO & OOO | Short localized GMT format | GMT-8 | 17182 * | | OOOO | Long localized GMT format | GMT-08:00 | 17183 * 17184 * 17185 * ### Format examples 17186 * 17187 * These examples transform a date into various formats, 17188 * assuming that `dateObj` is a JavaScript `Date` object for 17189 * year: 2015, month: 6, day: 15, hour: 21, minute: 43, second: 11, 17190 * given in the local time for the `en-US` locale. 17191 * 17192 * ``` 17193 * {{ dateObj | date }} // output is 'Jun 15, 2015' 17194 * {{ dateObj | date:'medium' }} // output is 'Jun 15, 2015, 9:43:11 PM' 17195 * {{ dateObj | date:'shortTime' }} // output is '9:43 PM' 17196 * {{ dateObj | date:'mm:ss' }} // output is '43:11' 17197 * ``` 17198 * 17199 * ### Usage example 17200 * 17201 * The following component uses a date pipe to display the current date in different formats. 17202 * 17203 * ``` 17204 * @Component({ 17205 * selector: 'date-pipe', 17206 * template: `<div> 17207 * <p>Today is {{today | date}}</p> 17208 * <p>Or if you prefer, {{today | date:'fullDate'}}</p> 17209 * <p>The time is {{today | date:'h:mm a z'}}</p> 17210 * </div>` 17211 * }) 17212 * // Get the current date and time as a date-time value. 17213 * export class DatePipeComponent { 17214 * today: number = Date.now(); 17215 * } 17216 * ``` 17217 * 17218 * @publicApi 17219 */ 17220// clang-format on 17221 17222class DatePipe { 17223 constructor(locale, defaultTimezone) { 17224 this.locale = locale; 17225 this.defaultTimezone = defaultTimezone; 17226 } 17227 17228 transform(value, format = 'mediumDate', timezone, locale) { 17229 if (value == null || value === '' || value !== value) return null; 17230 17231 try { 17232 return formatDate(value, format, locale || this.locale, timezone ?? this.defaultTimezone ?? undefined); 17233 } catch (error) {
17234 throw invalidPipeArgumentError(DatePipe, error.message); 17235 } 17236 } 17237 17238} 17239 17240DatePipe.ɵfac = function DatePipe_Factory(t) { 17241 return new (t || DatePipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID, 16), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](DATE_PIPE_DEFAULT_TIMEZONE, 24)); 17242}; 17243 17244DatePipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ 17245 name: "date", 17246 type: DatePipe, 17247 pure: true, 17248 standalone: true 17249}); 17250 17251(function () { 17252 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](DatePipe, [{ 17253 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe, 17254 args: [{ 17255 name: 'date', 17256 pure: true, 17257 standalone: true 17258 }] 17259 }], function () { 17260 return [{ 17261 type: undefined, 17262 decorators: [{ 17263 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 17264 args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID] 17265 }] 17266 }, { 17267 type: undefined, 17268 decorators: [{ 17269 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 17270 args: [DATE_PIPE_DEFAULT_TIMEZONE] 17271 }, { 17272 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 17273 }] 17274 }]; 17275 }, null); 17276})(); 17277/** 17278 * @license 17279 * Copyright Google LLC All Rights Reserved. 17280 * 17281 * Use of this source code is governed by an MIT-style license that can be 17282 * found in the LICENSE file at https://angular.io/license 17283 */ 17284 17285 17286const _INTERPOLATION_REGEXP = /#/g; 17287/** 17288 * @ngModule CommonModule 17289 * @description 17290 * 17291 * Maps a value to a string that pluralizes the value according to locale rules. 17292 * 17293 * @usageNotes 17294 * 17295 * ### Example 17296 * 17297 * {@example common/pipes/ts/i18n_pipe.ts region='I18nPluralPipeComponent'} 17298 * 17299 * @publicApi 17300 */ 17301 17302class I18nPluralPipe { 17303 constructor(_localization) { 17304 this._localization = _localization; 17305 } 17306 /** 17307 * @param value the number to be formatted 17308 * @param pluralMap an object that mimics the ICU format, see 17309 * https://unicode-org.github.io/icu/userguide/format_parse/messages/. 17310 * @param locale a `string` defining the locale to use (uses the current {@link LOCALE_ID} by 17311 * default). 17312 */ 17313 17314 17315 transform(value, pluralMap, locale) { 17316 if (value == null) return ''; 17317 17318 if (typeof pluralMap !== 'object' || pluralMap === null) { 17319 throw invalidPipeArgumentError(I18nPluralPipe, pluralMap); 17320 } 17321 17322 const key = getPluralCategory(value, Object.keys(pluralMap), this._localization, locale); 17323 return pluralMap[key].replace(_INTERPOLATION_REGEXP, value.toString()); 17324 } 17325 17326} 17327 17328I18nPluralPipe.ɵfac = function I18nPluralPipe_Factory(t) { 17329 return new (t || I18nPluralPipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NgLocalization, 16)); 17330}; 17331 17332I18nPluralPipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ 17333 name: "i18nPlural", 17334 type: I18nPluralPipe, 17335 pure: true, 17336 standalone: true 17337}); 17338 17339(function () { 17340 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](I18nPluralPipe, [{ 17341 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe, 17342 args: [{ 17343 name: 'i18nPlural', 17344 pure: true, 17345 standalone: true 17346 }] 17347 }], function () { 17348 return [{ 17349 type: NgLocalization 17350 }]; 17351 }, null); 17352})(); 17353/** 17354 * @license 17355 * Copyright Google LLC All Rights Reserved. 17356 * 17357 * Use of this source code is governed by an MIT-style license that can be 17358 * found in the LICENSE file at https://angular.io/license 17359 */ 17360 17361/** 17362 * @ngModule CommonModule 17363 * @description 17364 * 17365 * Generic selector that displays the string that matches the current value. 17366 * 17367 * If none of the keys of the `mapping` match the `value`, then the content 17368 * of the `other` key is returned when present, otherwise an empty string is returned. 17369 * 17370 * @usageNotes 17371 * 17372 * ### Example 17373 * 17374 * {@example common/pipes/ts/i18n_pipe.ts region='I18nSelectPipeComponent'} 17375 * 17376 * @publicApi 17377 */ 17378 17379 17380class I18nSelectPipe { 17381 /** 17382 * @param value a string to be internationalized. 17383 * @param mapping an object that indicates the text that should be displayed 17384 * for different values of the provided `value`. 17385 */ 17386 transform(value, mapping) { 17387 if (value == null) return ''; 17388 17389 if (typeof mapping !== 'object' || typeof value !== 'string') {
17390 throw invalidPipeArgumentError(I18nSelectPipe, mapping); 17391 } 17392 17393 if (mapping.hasOwnProperty(value)) { 17394 return mapping[value]; 17395 } 17396 17397 if (mapping.hasOwnProperty('other')) { 17398 return mapping['other']; 17399 } 17400 17401 return ''; 17402 } 17403 17404} 17405 17406I18nSelectPipe.ɵfac = function I18nSelectPipe_Factory(t) { 17407 return new (t || I18nSelectPipe)(); 17408}; 17409 17410I18nSelectPipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ 17411 name: "i18nSelect", 17412 type: I18nSelectPipe, 17413 pure: true, 17414 standalone: true 17415}); 17416 17417(function () { 17418 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](I18nSelectPipe, [{ 17419 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe, 17420 args: [{ 17421 name: 'i18nSelect', 17422 pure: true, 17423 standalone: true 17424 }] 17425 }], null, null); 17426})(); 17427/** 17428 * @license 17429 * Copyright Google LLC All Rights Reserved. 17430 * 17431 * Use of this source code is governed by an MIT-style license that can be 17432 * found in the LICENSE file at https://angular.io/license 17433 */ 17434 17435/** 17436 * @ngModule CommonModule 17437 * @description 17438 * 17439 * Converts a value into its JSON-format representation. Useful for debugging. 17440 * 17441 * @usageNotes 17442 * 17443 * The following component uses a JSON pipe to convert an object 17444 * to JSON format, and displays the string in both formats for comparison. 17445 * 17446 * {@example common/pipes/ts/json_pipe.ts region='JsonPipe'} 17447 * 17448 * @publicApi 17449 */ 17450 17451 17452class JsonPipe { 17453 /** 17454 * @param value A value of any type to convert into a JSON-format string. 17455 */ 17456 transform(value) { 17457 return JSON.stringify(value, null, 2); 17458 } 17459 17460} 17461 17462JsonPipe.ɵfac = function JsonPipe_Factory(t) { 17463 return new (t || JsonPipe)(); 17464}; 17465 17466JsonPipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ 17467 name: "json", 17468 type: JsonPipe, 17469 pure: false, 17470 standalone: true 17471}); 17472 17473(function () { 17474 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](JsonPipe, [{ 17475 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe, 17476 args: [{ 17477 name: 'json', 17478 pure: false, 17479 standalone: true 17480 }] 17481 }], null, null); 17482})(); 17483/** 17484 * @license 17485 * Copyright Google LLC All Rights Reserved. 17486 * 17487 * Use of this source code is governed by an MIT-style license that can be 17488 * found in the LICENSE file at https://angular.io/license 17489 */ 17490 17491 17492function makeKeyValuePair(key, value) { 17493 return { 17494 key: key, 17495 value: value 17496 }; 17497} 17498/** 17499 * @ngModule CommonModule 17500 * @description 17501 * 17502 * Transforms Object or Map into an array of key value pairs. 17503 * 17504 * The output array will be ordered by keys. 17505 * By default the comparator will be by Unicode point value. 17506 * You can optionally pass a compareFn if your keys are complex types. 17507 * 17508 * @usageNotes 17509 * ### Examples 17510 * 17511 * This examples show how an Object or a Map can be iterated by ngFor with the use of this 17512 * keyvalue pipe. 17513 * 17514 * {@example common/pipes/ts/keyvalue_pipe.ts region='KeyValuePipe'} 17515 * 17516 * @publicApi 17517 */ 17518 17519 17520class KeyValuePipe { 17521 constructor(differs) { 17522 this.differs = differs; 17523 this.keyValues = []; 17524 this.compareFn = defaultComparator; 17525 } 17526 17527 transform(input, compareFn = defaultComparator) { 17528 if (!input || !(input instanceof Map) && typeof input !== 'object') { 17529 return null; 17530 } 17531 17532 if (!this.differ) { 17533 // make a differ for whatever type we've been passed in 17534 this.differ = this.differs.find(input).create(); 17535 } 17536 17537 const differChanges = this.differ.diff(input); 17538 const compareFnChanged = compareFn !== this.compareFn; 17539 17540 if (differChanges) { 17541 this.keyValues = [];
17542 differChanges.forEachItem(r => { 17543 this.keyValues.push(makeKeyValuePair(r.key, r.currentValue)); 17544 }); 17545 } 17546 17547 if (differChanges || compareFnChanged) { 17548 this.keyValues.sort(compareFn); 17549 this.compareFn = compareFn; 17550 } 17551 17552 return this.keyValues; 17553 } 17554 17555} 17556 17557KeyValuePipe.ɵfac = function KeyValuePipe_Factory(t) { 17558 return new (t || KeyValuePipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.KeyValueDiffers, 16)); 17559}; 17560 17561KeyValuePipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ 17562 name: "keyvalue", 17563 type: KeyValuePipe, 17564 pure: false, 17565 standalone: true 17566}); 17567 17568(function () { 17569 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](KeyValuePipe, [{ 17570 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe, 17571 args: [{ 17572 name: 'keyvalue', 17573 pure: false, 17574 standalone: true 17575 }] 17576 }], function () { 17577 return [{ 17578 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.KeyValueDiffers 17579 }]; 17580 }, null); 17581})(); 17582 17583function defaultComparator(keyValueA, keyValueB) { 17584 const a = keyValueA.key; 17585 const b = keyValueB.key; // if same exit with 0; 17586 17587 if (a === b) return 0; // make sure that undefined are at the end of the sort. 17588 17589 if (a === undefined) return 1; 17590 if (b === undefined) return -1; // make sure that nulls are at the end of the sort. 17591 17592 if (a === null) return 1; 17593 if (b === null) return -1; 17594 17595 if (typeof a == 'string' && typeof b == 'string') { 17596 return a < b ? -1 : 1; 17597 } 17598 17599 if (typeof a == 'number' && typeof b == 'number') { 17600 return a - b; 17601 } 17602 17603 if (typeof a == 'boolean' && typeof b == 'boolean') { 17604 return a < b ? -1 : 1; 17605 } // `a` and `b` are of different types. Compare their string values. 17606 17607 17608 const aString = String(a); 17609 const bString = String(b); 17610 return aString == bString ? 0 : aString < bString ? -1 : 1; 17611} 17612/** 17613 * @license 17614 * Copyright Google LLC All Rights Reserved. 17615 * 17616 * Use of this source code is governed by an MIT-style license that can be 17617 * found in the LICENSE file at https://angular.io/license 17618 */ 17619 17620/** 17621 * @ngModule CommonModule 17622 * @description 17623 * 17624 * Formats a value according to digit options and locale rules. 17625 * Locale determines group sizing and separator, 17626 * decimal point character, and other locale-specific configurations. 17627 * 17628 * @see `formatNumber()` 17629 * 17630 * @usageNotes 17631 * 17632 * ### digitsInfo 17633 * 17634 * The value's decimal representation is specified by the `digitsInfo` 17635 * parameter, written in the following format:<br> 17636 * 17637 * ``` 17638 * {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits} 17639 * ``` 17640 * 17641 * - `minIntegerDigits`: 17642 * The minimum number of integer digits before the decimal point. 17643 * Default is 1. 17644 * 17645 * - `minFractionDigits`: 17646 * The minimum number of digits after the decimal point. 17647 * Default is 0. 17648 * 17649 * - `maxFractionDigits`: 17650 * The maximum number of digits after the decimal point. 17651 * Default is 3. 17652 * 17653 * If the formatted value is truncated it will be rounded using the "to-nearest" method: 17654 * 17655 * ``` 17656 * {{3.6 | number: '1.0-0'}} 17657 * <!--will output '4'--> 17658 * 17659 * {{-3.6 | number:'1.0-0'}} 17660 * <!--will output '-4'--> 17661 * ``` 17662 * 17663 * ### locale 17664 * 17665 * `locale` will format a value according to locale rules. 17666 * Locale determines group sizing and separator, 17667 * decimal point character, and other locale-specific configurations. 17668 * 17669 * When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default. 17670 * 17671 * See [Setting your app locale](guide/i18n-common-locale-id). 17672 * 17673 * ### Example 17674 * 17675 * The following code shows how the pipe transforms values 17676 * according to various format specifications, 17677 * where the caller's default locale is `en-US`. 17678 * 17679 * <code-example path="common/pipes/ts/number_pipe.ts" region='NumberPipe'></code-example> 17680 * 17681 * @publicApi 17682 */ 17683 17684 17685class DecimalPipe { 17686 constructor(_locale) { 17687 this._locale = _locale; 17688 } 17689 /** 17690 * @param value The value to be formatted. 17691 * @param digitsInfo Sets digit and decimal representation. 17692 * [See more](#digitsinfo). 17693 * @param locale Specifies what locale format rules to use. 17694 * [See more](#locale). 17695 */ 17696 17697 17698 transform(value, digitsInfo, locale) { 17699 if (!isValue(value)) return null; 17700 locale = locale || this._locale; 17701 17702 try { 17703 const num = strToNumber(value); 17704 return formatNumber(num, locale, digitsInfo); 17705 } catch (error) {
17706 throw invalidPipeArgumentError(DecimalPipe, error.message); 17707 } 17708 } 17709 17710} 17711 17712DecimalPipe.ɵfac = function DecimalPipe_Factory(t) { 17713 return new (t || DecimalPipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID, 16)); 17714}; 17715 17716DecimalPipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ 17717 name: "number", 17718 type: DecimalPipe, 17719 pure: true, 17720 standalone: true 17721}); 17722 17723(function () { 17724 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](DecimalPipe, [{ 17725 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe, 17726 args: [{ 17727 name: 'number', 17728 standalone: true 17729 }] 17730 }], function () { 17731 return [{ 17732 type: undefined, 17733 decorators: [{ 17734 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 17735 args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID] 17736 }] 17737 }]; 17738 }, null); 17739})(); 17740/** 17741 * @ngModule CommonModule 17742 * @description 17743 * 17744 * Transforms a number to a percentage 17745 * string, formatted according to locale rules that determine group sizing and 17746 * separator, decimal-point character, and other locale-specific 17747 * configurations. 17748 * 17749 * @see `formatPercent()` 17750 * 17751 * @usageNotes 17752 * The following code shows how the pipe transforms numbers 17753 * into text strings, according to various format specifications, 17754 * where the caller's default locale is `en-US`. 17755 * 17756 * <code-example path="common/pipes/ts/percent_pipe.ts" region='PercentPipe'></code-example> 17757 * 17758 * @publicApi 17759 */ 17760 17761 17762class PercentPipe { 17763 constructor(_locale) { 17764 this._locale = _locale; 17765 } 17766 /** 17767 * 17768 * @param value The number to be formatted as a percentage. 17769 * @param digitsInfo Decimal representation options, specified by a string 17770 * in the following format:<br> 17771 * <code>{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}</code>. 17772 * - `minIntegerDigits`: The minimum number of integer digits before the decimal point. 17773 * Default is `1`. 17774 * - `minFractionDigits`: The minimum number of digits after the decimal point. 17775 * Default is `0`. 17776 * - `maxFractionDigits`: The maximum number of digits after the decimal point. 17777 * Default is `0`. 17778 * @param locale A locale code for the locale format rules to use. 17779 * When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default. 17780 * See [Setting your app locale](guide/i18n-common-locale-id). 17781 */ 17782 17783 17784 transform(value, digitsInfo, locale) { 17785 if (!isValue(value)) return null; 17786 locale = locale || this._locale; 17787 17788 try { 17789 const num = strToNumber(value); 17790 return formatPercent(num, locale, digitsInfo); 17791 } catch (error) { 17792 throw invalidPipeArgumentError(PercentPipe, error.message); 17793 } 17794 } 17795 17796} 17797 17798PercentPipe.ɵfac = function PercentPipe_Factory(t) { 17799 return new (t || PercentPipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID, 16)); 17800}; 17801 17802PercentPipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ 17803 name: "percent", 17804 type: PercentPipe, 17805 pure: true, 17806 standalone: true 17807}); 17808 17809(function () { 17810 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](PercentPipe, [{ 17811 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe, 17812 args: [{ 17813 name: 'percent', 17814 standalone: true 17815 }] 17816 }], function () { 17817 return [{ 17818 type: undefined, 17819 decorators: [{ 17820 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 17821 args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID] 17822 }] 17823 }]; 17824 }, null); 17825})(); 17826/** 17827 * @ngModule CommonModule 17828 * @description 17829 * 17830 * Transforms a number to a currency string, formatted according to locale rules 17831 * that determine group sizing and separator, decimal-point character, 17832 * and other locale-specific configurations. 17833 * 17834 * {@a currency-code-deprecation} 17835 * <div class="alert is-helpful"> 17836 * 17837 * **Deprecation notice:** 17838 * 17839 * The default currency code is currently always `USD` but this is deprecated from v9. 17840 * 17841 * **In v11 the default currency code will be taken from the current locale identified by 17842 * the `LOCALE_ID` token. See the [i18n guide](guide/i18n-common-locale-id) for 17843 * more information.** 17844 * 17845 * If you need the previous behavior then set it by creating a `DEFAULT_CURRENCY_CODE` provider in 17846 * your application `NgModule`: 17847 * 17848 * ```ts 17849 * {provide: DEFAULT_CURRENCY_CODE, useValue: 'USD'} 17850 * ``` 17851 * 17852 * </div> 17853 * 17854 * @see `getCurrencySymbol()` 17855 * @see `formatCurrency()` 17856 * 17857 * @usageNotes 17858 * The following code shows how the pipe transforms numbers
17859 * into text strings, according to various format specifications, 17860 * where the caller's default locale is `en-US`. 17861 * 17862 * <code-example path="common/pipes/ts/currency_pipe.ts" region='CurrencyPipe'></code-example> 17863 * 17864 * @publicApi 17865 */ 17866 17867 17868class CurrencyPipe { 17869 constructor(_locale, _defaultCurrencyCode = 'USD') { 17870 this._locale = _locale; 17871 this._defaultCurrencyCode = _defaultCurrencyCode; 17872 } 17873 /** 17874 * 17875 * @param value The number to be formatted as currency. 17876 * @param currencyCode The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code, 17877 * such as `USD` for the US dollar and `EUR` for the euro. The default currency code can be 17878 * configured using the `DEFAULT_CURRENCY_CODE` injection token. 17879 * @param display The format for the currency indicator. One of the following: 17880 * - `code`: Show the code (such as `USD`). 17881 * - `symbol`(default): Show the symbol (such as `$`). 17882 * - `symbol-narrow`: Use the narrow symbol for locales that have two symbols for their 17883 * currency. 17884 * For example, the Canadian dollar CAD has the symbol `CA$` and the symbol-narrow `$`. If the 17885 * locale has no narrow symbol, uses the standard symbol for the locale. 17886 * - String: Use the given string value instead of a code or a symbol. 17887 * For example, an empty string will suppress the currency & symbol. 17888 * - Boolean (marked deprecated in v5): `true` for symbol and false for `code`. 17889 * 17890 * @param digitsInfo Decimal representation options, specified by a string 17891 * in the following format:<br> 17892 * <code>{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}</code>. 17893 * - `minIntegerDigits`: The minimum number of integer digits before the decimal point. 17894 * Default is `1`. 17895 * - `minFractionDigits`: The minimum number of digits after the decimal point. 17896 * Default is `2`. 17897 * - `maxFractionDigits`: The maximum number of digits after the decimal point. 17898 * Default is `2`. 17899 * If not provided, the number will be formatted with the proper amount of digits, 17900 * depending on what the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) specifies. 17901 * For example, the Canadian dollar has 2 digits, whereas the Chilean peso has none. 17902 * @param locale A locale code for the locale format rules to use. 17903 * When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default. 17904 * See [Setting your app locale](guide/i18n-common-locale-id). 17905 */ 17906 17907 17908 transform(value, currencyCode = this._defaultCurrencyCode, display = 'symbol', digitsInfo, locale) { 17909 if (!isValue(value)) return null; 17910 locale = locale || this._locale; 17911 17912 if (typeof display === 'boolean') { 17913 if ((typeof ngDevMode === 'undefined' || ngDevMode) && console && console.warn) { 17914 console.warn(`Warning: the currency pipe has been changed in Angular v5. The symbolDisplay option (third parameter) is now a string instead of a boolean. The accepted values are "code", "symbol" or "symbol-narrow".`); 17915 } 17916 17917 display = display ? 'symbol' : 'code'; 17918 } 17919 17920 let currency = currencyCode || this._defaultCurrencyCode; 17921 17922 if (display !== 'code') { 17923 if (display === 'symbol' || display === 'symbol-narrow') { 17924 currency = getCurrencySymbol(currency, display === 'symbol' ? 'wide' : 'narrow', locale); 17925 } else { 17926 currency = display; 17927 } 17928 } 17929 17930 try { 17931 const num = strToNumber(value); 17932 return formatCurrency(num, locale, currency, currencyCode, digitsInfo); 17933 } catch (error) { 17934 throw invalidPipeArgumentError(CurrencyPipe, error.message); 17935 } 17936 } 17937 17938} 17939 17940CurrencyPipe.ɵfac = function CurrencyPipe_Factory(t) { 17941 return new (t || CurrencyPipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID, 16), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_CURRENCY_CODE, 16)); 17942}; 17943 17944CurrencyPipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ 17945 name: "currency", 17946 type: CurrencyPipe, 17947 pure: true, 17948 standalone: true 17949}); 17950 17951(function () { 17952 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](CurrencyPipe, [{ 17953 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe, 17954 args: [{ 17955 name: 'currency', 17956 standalone: true 17957 }] 17958 }], function () { 17959 return [{ 17960 type: undefined, 17961 decorators: [{ 17962 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 17963 args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.LOCALE_ID] 17964 }] 17965 }, {
17966 type: undefined, 17967 decorators: [{ 17968 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 17969 args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.DEFAULT_CURRENCY_CODE] 17970 }] 17971 }]; 17972 }, null); 17973})(); 17974 17975function isValue(value) { 17976 return !(value == null || value === '' || value !== value); 17977} 17978/** 17979 * Transforms a string into a number (if needed). 17980 */ 17981 17982 17983function strToNumber(value) { 17984 // Convert strings to numbers 17985 if (typeof value === 'string' && !isNaN(Number(value) - parseFloat(value))) { 17986 return Number(value); 17987 } 17988 17989 if (typeof value !== 'number') { 17990 throw new Error(`${value} is not a number`); 17991 } 17992 17993 return value; 17994} 17995/** 17996 * @license 17997 * Copyright Google LLC All Rights Reserved. 17998 * 17999 * Use of this source code is governed by an MIT-style license that can be 18000 * found in the LICENSE file at https://angular.io/license 18001 */ 18002 18003/** 18004 * @ngModule CommonModule 18005 * @description 18006 * 18007 * Creates a new `Array` or `String` containing a subset (slice) of the elements. 18008 * 18009 * @usageNotes 18010 * 18011 * All behavior is based on the expected behavior of the JavaScript API `Array.prototype.slice()` 18012 * and `String.prototype.slice()`. 18013 * 18014 * When operating on an `Array`, the returned `Array` is always a copy even when all 18015 * the elements are being returned. 18016 * 18017 * When operating on a blank value, the pipe returns the blank value. 18018 * 18019 * ### List Example 18020 * 18021 * This `ngFor` example: 18022 * 18023 * {@example common/pipes/ts/slice_pipe.ts region='SlicePipe_list'} 18024 * 18025 * produces the following: 18026 * 18027 * ```html 18028 * <li>b</li> 18029 * <li>c</li> 18030 * ``` 18031 * 18032 * ### String Examples 18033 * 18034 * {@example common/pipes/ts/slice_pipe.ts region='SlicePipe_string'} 18035 * 18036 * @publicApi 18037 */ 18038 18039 18040class SlicePipe { 18041 transform(value, start, end) { 18042 if (value == null) return null; 18043 18044 if (!this.supports(value)) { 18045 throw invalidPipeArgumentError(SlicePipe, value); 18046 } 18047 18048 return value.slice(start, end); 18049 } 18050 18051 supports(obj) { 18052 return typeof obj === 'string' || Array.isArray(obj); 18053 } 18054 18055} 18056 18057SlicePipe.ɵfac = function SlicePipe_Factory(t) { 18058 return new (t || SlicePipe)(); 18059}; 18060 18061SlicePipe.ɵpipe = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ 18062 name: "slice", 18063 type: SlicePipe, 18064 pure: false, 18065 standalone: true 18066}); 18067 18068(function () { 18069 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](SlicePipe, [{ 18070 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Pipe, 18071 args: [{ 18072 name: 'slice', 18073 pure: false, 18074 standalone: true 18075 }] 18076 }], null, null); 18077})(); 18078/** 18079 * @license 18080 * Copyright Google LLC All Rights Reserved. 18081 * 18082 * Use of this source code is governed by an MIT-style license that can be 18083 * found in the LICENSE file at https://angular.io/license 18084 */ 18085 18086/** 18087 * A collection of Angular pipes that are likely to be used in each and every application. 18088 */ 18089 18090 18091const COMMON_PIPES = [AsyncPipe, UpperCasePipe, LowerCasePipe, JsonPipe, SlicePipe, DecimalPipe, PercentPipe, TitleCasePipe, CurrencyPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, KeyValuePipe]; 18092/** 18093 * @license 18094 * Copyright Google LLC All Rights Reserved. 18095 * 18096 * Use of this source code is governed by an MIT-style license that can be 18097 * found in the LICENSE file at https://angular.io/license 18098 */ 18099// Note: This does not contain the location providers, 18100// as they need some platform specific implementations to work. 18101 18102/** 18103 * Exports all the basic Angular directives and pipes, 18104 * such as `NgIf`, `NgForOf`, `DecimalPipe`, and so on. 18105 * Re-exported by `BrowserModule`, which is included automatically in the root 18106 * `AppModule` when you create a new app with the CLI `new` command. 18107 * 18108 * @publicApi 18109 */ 18110 18111class CommonModule {} 18112 18113CommonModule.ɵfac = function CommonModule_Factory(t) { 18114 return new (t || CommonModule)(); 18115}; 18116 18117CommonModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({ 18118 type: CommonModule, 18119 imports: [NgClass, NgComponentOutlet, NgForOf, NgIf, NgTemplateOutlet, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgPlural, NgPluralCase, AsyncPipe, UpperCasePipe, LowerCasePipe, JsonPipe, SlicePipe, DecimalPipe, PercentPipe, TitleCasePipe, CurrencyPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, KeyValuePipe], 18120 exports: [NgClass, NgComponentOutlet, NgForOf, NgIf, NgTemplateOutlet, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgPlural, NgPluralCase, AsyncPipe, UpperCasePipe, LowerCasePipe, JsonPipe, SlicePipe, DecimalPipe, PercentPipe, TitleCasePipe, CurrencyPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, KeyValuePipe] 18121}); 18122CommonModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({}); 18123 18124(function () { 18125 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](CommonModule, [{ 18126 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule, 18127 args: [{ 18128 imports: [COMMON_DIRECTIVES, COMMON_PIPES], 18129 exports: [COMMON_DIRECTIVES, COMMON_PIPES] 18130 }] 18131 }], null, null); 18132})(); 18133/** 18134 * @license 18135 * Copyright Google LLC All Rights Reserved. 18136 * 18137 * Use of this source code is governed by an MIT-style license that can be 18138 * found in the LICENSE file at https://angular.io/license 18139 */ 18140 18141 18142const PLATFORM_BROWSER_ID = 'browser'; 18143const PLATFORM_SERVER_ID = 'server'; 18144const PLATFORM_WORKER_APP_ID = 'browserWorkerApp'; 18145const PLATFORM_WORKER_UI_ID = 'browserWorkerUi'; 18146/** 18147 * Returns whether a platform id represents a browser platform. 18148 * @publicApi 18149 */ 18150 18151function isPlatformBrowser(platformId) { 18152 return platformId === PLATFORM_BROWSER_ID; 18153} 18154/** 18155 * Returns whether a platform id represents a server platform. 18156 * @publicApi 18157 */ 18158 18159 18160function isPlatformServer(platformId) { 18161 return platformId === PLATFORM_SERVER_ID; 18162} 18163/** 18164 * Returns whether a platform id represents a web worker app platform. 18165 * @publicApi 18166 */ 18167 18168 18169function isPlatformWorkerApp(platformId) { 18170 return platformId === PLATFORM_WORKER_APP_ID; 18171} 18172/** 18173 * Returns whether a platform id represents a web worker UI platform. 18174 * @publicApi 18175 */ 18176 18177 18178function isPlatformWorkerUi(platformId) { 18179 return platformId === PLATFORM_WORKER_UI_ID; 18180} 18181/** 18182 * @license 18183 * Copyright Google LLC All Rights Reserved. 18184 * 18185 * Use of this source code is governed by an MIT-style license that can be 18186 * found in the LICENSE file at https://angular.io/license 18187 */ 18188 18189/** 18190 * @publicApi 18191 */ 18192 18193 18194const VERSION = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.Version('14.2.10'); 18195/** 18196 * @license 18197 * Copyright Google LLC All Rights Reserved. 18198 * 18199 * Use of this source code is governed by an MIT-style license that can be 18200 * found in the LICENSE file at https://angular.io/license 18201 */ 18202 18203/** 18204 * Defines a scroll position manager. Implemented by `BrowserViewportScroller`. 18205 * 18206 * @publicApi 18207 */ 18208 18209class ViewportScroller {} // De-sugared tree-shakable injection 18210// See #23917 18211 18212/** @nocollapse */ 18213 18214 18215ViewportScroller.ɵprov = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"])({ 18216 token: ViewportScroller, 18217 providedIn: 'root', 18218 factory: () => new BrowserViewportScroller((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(DOCUMENT), window) 18219}
18219); 18220/** 18221 * Manages the scroll position for a browser window. 18222 */ 18223 18224class BrowserViewportScroller { 18225 constructor(document, window) { 18226 this.document = document; 18227 this.window = window; 18228 18229 this.offset = () => [0, 0]; 18230 } 18231 /** 18232 * Configures the top offset used when scrolling to an anchor. 18233 * @param offset A position in screen coordinates (a tuple with x and y values) 18234 * or a function that returns the top offset position. 18235 * 18236 */ 18237 18238 18239 setOffset(offset) { 18240 if (Array.isArray(offset)) { 18241 this.offset = () => offset; 18242 } else { 18243 this.offset = offset; 18244 } 18245 } 18246 /** 18247 * Retrieves the current scroll position. 18248 * @returns The position in screen coordinates. 18249 */ 18250 18251 18252 getScrollPosition() { 18253 if (this.supportsScrolling()) { 18254 return [this.window.pageXOffset, this.window.pageYOffset]; 18255 } else { 18256 return [0, 0]; 18257 } 18258 } 18259 /** 18260 * Sets the scroll position. 18261 * @param position The new position in screen coordinates. 18262 */ 18263 18264 18265 scrollToPosition(position) { 18266 if (this.supportsScrolling()) { 18267 this.window.scrollTo(position[0], position[1]); 18268 } 18269 } 18270 /** 18271 * Scrolls to an element and attempts to focus the element. 18272 * 18273 * Note that the function name here is misleading in that the target string may be an ID for a 18274 * non-anchor element. 18275 * 18276 * @param target The ID of an element or name of the anchor. 18277 * 18278 * @see https://html.spec.whatwg.org/#the-indicated-part-of-the-document 18279 * @see https://html.spec.whatwg.org/#scroll-to-fragid 18280 */ 18281 18282 18283 scrollToAnchor(target) { 18284 if (!this.supportsScrolling()) { 18285 return; 18286 } 18287 18288 const elSelected = findAnchorFromDocument(this.document, target); 18289 18290 if (elSelected) { 18291 this.scrollToElement(elSelected); // After scrolling to the element, the spec dictates that we follow the focus steps for the 18292 // target. Rather than following the robust steps, simply attempt focus. 18293 // 18294 // @see https://html.spec.whatwg.org/#get-the-focusable-area 18295 // @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/focus 18296 // @see https://html.spec.whatwg.org/#focusable-area 18297 18298 elSelected.focus(); 18299 } 18300 } 18301 /** 18302 * Disables automatic scroll restoration provided by the browser. 18303 */ 18304 18305 18306 setHistoryScrollRestoration(scrollRestoration) { 18307 if (this.supportScrollRestoration()) { 18308 const history = this.window.history; 18309 18310 if (history && history.scrollRestoration) { 18311 history.scrollRestoration = scrollRestoration; 18312 } 18313 } 18314 } 18315 /** 18316 * Scrolls to an element using the native offset and the specified offset set on this scroller. 18317 * 18318 * The offset can be used when we know that there is a floating header and scrolling naively to an 18319 * element (ex: `scrollIntoView`) leaves the element hidden behind the floating header. 18320 */ 18321 18322 18323 scrollToElement(el) { 18324 const rect = el.getBoundingClientRect(); 18325 const left = rect.left + this.window.pageXOffset; 18326 const top = rect.top + this.window.pageYOffset; 18327 const offset = this.offset(); 18328 this.window.scrollTo(left - offset[0], top - offset[1]); 18329 } 18330 /** 18331 * We only support scroll restoration when we can get a hold of window. 18332 * This means that we do not support this behavior when running in a web worker. 18333 * 18334 * Lifting this restriction right now would require more changes in the dom adapter. 18335 * Since webworkers aren't widely used, we will lift it once RouterScroller is 18336 * battle-tested. 18337 */ 18338 18339 18340 supportScrollRestoration() { 18341 try { 18342 if (!this.supportsScrolling()) { 18343 return false; 18344 } // The `scrollRestoration` property could be on the `history` instance or its prototype. 18345 18346 18347 const scrollRestorationDescriptor = getScrollRestorationProperty(this.window.history) || getScrollRestorationProperty(Object.getPrototypeOf(this.window.history)); // We can write to the `scrollRestoration` property if it is a writable data field or it has a 18348 // setter function. 18349 18350 return !!scrollRestorationDescriptor && !!(scrollRestorationDescriptor.writable || scrollRestorationDescriptor.set); 18351 } catch { 18352 return false;
18353 } 18354 } 18355 18356 supportsScrolling() { 18357 try { 18358 return !!this.window && !!this.window.scrollTo && 'pageXOffset' in this.window; 18359 } catch { 18360 return false; 18361 } 18362 } 18363 18364} 18365 18366function getScrollRestorationProperty(obj) { 18367 return Object.getOwnPropertyDescriptor(obj, 'scrollRestoration'); 18368} 18369 18370function findAnchorFromDocument(document, target) { 18371 const documentResult = document.getElementById(target) || document.getElementsByName(target)[0]; 18372 18373 if (documentResult) { 18374 return documentResult; 18375 } // `getElementById` and `getElementsByName` won't pierce through the shadow DOM so we 18376 // have to traverse the DOM manually and do the lookup through the shadow roots. 18377 18378 18379 if (typeof document.createTreeWalker === 'function' && document.body && (document.body.createShadowRoot || document.body.attachShadow)) { 18380 const treeWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT); 18381 let currentNode = treeWalker.currentNode; 18382 18383 while (currentNode) { 18384 const shadowRoot = currentNode.shadowRoot; 18385 18386 if (shadowRoot) { 18387 // Note that `ShadowRoot` doesn't support `getElementsByName` 18388 // so we have to fall back to `querySelector`. 18389 const result = shadowRoot.getElementById(target) || shadowRoot.querySelector(`[name="${target}"]`); 18390 18391 if (result) { 18392 return result; 18393 } 18394 } 18395 18396 currentNode = treeWalker.nextNode(); 18397 } 18398 } 18399 18400 return null; 18401} 18402/** 18403 * Provides an empty implementation of the viewport scroller. 18404 */ 18405 18406 18407class NullViewportScroller { 18408 /** 18409 * Empty implementation 18410 */ 18411 setOffset(offset) {} 18412 /** 18413 * Empty implementation 18414 */ 18415 18416 18417 getScrollPosition() { 18418 return [0, 0]; 18419 } 18420 /** 18421 * Empty implementation 18422 */ 18423 18424 18425 scrollToPosition(position) {} 18426 /** 18427 * Empty implementation 18428 */ 18429 18430 18431 scrollToAnchor(anchor) {} 18432 /** 18433 * Empty implementation 18434 */ 18435 18436 18437 setHistoryScrollRestoration(scrollRestoration) {} 18438 18439} 18440/** 18441 * @license 18442 * Copyright Google LLC All Rights Reserved. 18443 * 18444 * Use of this source code is governed by an MIT-style license that can be 18445 * found in the LICENSE file at https://angular.io/license 18446 */ 18447 18448/** 18449 * A wrapper around the `XMLHttpRequest` constructor. 18450 * 18451 * @publicApi 18452 */ 18453 18454 18455class XhrFactory {} 18456/** 18457 * @license 18458 * Copyright Google LLC All Rights Reserved. 18459 * 18460 * Use of this source code is governed by an MIT-style license that can be 18461 * found in the LICENSE file at https://angular.io/license 18462 */ 18463 18464/** 18465 * Asserts that the application is in development mode. Throws an error if the application is in 18466 * production mode. This assert can be used to make sure that there is no dev-mode code invoked in 18467 * the prod mode accidentally. 18468 */ 18469 18470 18471function assertDevMode(checkName) { 18472 if (!ngDevMode) { 18473 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2958 18474 /* RuntimeErrorCode.UNEXPECTED_DEV_MODE_CHECK_IN_PROD_MODE */ 18475 , `Unexpected invocation of the ${checkName} in the prod mode. ` + `Please make sure that the prod mode is enabled for production builds.`); 18476 } 18477} 18478/** 18479 * @license 18480 * Copyright Google LLC All Rights Reserved. 18481 * 18482 * Use of this source code is governed by an MIT-style license that can be 18483 * found in the LICENSE file at https://angular.io/license 18484 */ 18485// Assembles directive details string, useful for error messages. 18486 18487 18488function imgDirectiveDetails(ngSrc, includeNgSrc = true) { 18489 const ngSrcInfo = includeNgSrc ? `(activated on an <img> element with the \`ngSrc="${ngSrc}"\`) ` : ''; 18490 return `The NgOptimizedImage directive ${ngSrcInfo}has detected that`; 18491} 18492/** 18493 * @license 18494 * Copyright Google LLC All Rights Reserved. 18495 * 18496 * Use of this source code is governed by an MIT-style license that can be 18497 * found in the LICENSE file at https://angular.io/license 18498 */ 18499// Converts a string that represents a URL into a URL class instance. 18500 18501 18502function getUrl(src, win) { 18503 // Don't use a base URL is the URL is absolute. 18504 return isAbsoluteUrl(src) ? new URL(src) : new URL(src, win.location.href); 18505} // Checks whether a URL is absolute (i.e. starts with `http://` or `https://`). 18506 18507 18508function isAbsoluteUrl(src) { 18509 return /^https?:\/\//.test(src); 18510} // Given a URL, extract the hostname part. 18511// If a URL is a relative one - the URL is returned as is. 18512 18513 18514function extractHostname(url) { 18515 return isAbsoluteUrl(url) ? new URL(url).hostname : url; 18516} 18517 18518function isValidPath(path) { 18519 const isString = typeof path === 'string'; 18520 18521 if (!isString || path.trim() === '') { 18522 return false;
18523 } // Calling new URL() will throw if the path string is malformed 18524 18525 18526 try { 18527 const url = new URL(path); 18528 return true; 18529 } catch { 18530 return false; 18531 } 18532} 18533 18534function normalizePath(path) { 18535 return path.endsWith('/') ? path.slice(0, -1) : path; 18536} 18537 18538function normalizeSrc(src) { 18539 return src.startsWith('/') ? src.slice(1) : src; 18540} 18541/** 18542 * @license 18543 * Copyright Google LLC All Rights Reserved. 18544 * 18545 * Use of this source code is governed by an MIT-style license that can be 18546 * found in the LICENSE file at https://angular.io/license 18547 */ 18548// Set of origins that are always excluded from the preconnect checks. 18549 18550 18551const INTERNAL_PRECONNECT_CHECK_BLOCKLIST = new Set(['localhost', '127.0.0.1', '0.0.0.0']); 18552/** 18553 * Multi-provider injection token to configure which origins should be excluded 18554 * from the preconnect checks. It can either be a single string or an array of strings 18555 * to represent a group of origins, for example: 18556 * 18557 * ```typescript 18558 * {provide: PRECONNECT_CHECK_BLOCKLIST, multi: true, useValue: 'https://your-domain.com'} 18559 * ``` 18560 * 18561 * or: 18562 * 18563 * ```typescript 18564 * {provide: PRECONNECT_CHECK_BLOCKLIST, multi: true, 18565 * useValue: ['https://your-domain-1.com', 'https://your-domain-2.com']} 18566 * ``` 18567 * 18568 * @publicApi 18569 * @developerPreview 18570 */ 18571 18572const PRECONNECT_CHECK_BLOCKLIST = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('PRECONNECT_CHECK_BLOCKLIST'); 18573/** 18574 * Contains the logic to detect whether an image, marked with the "priority" attribute 18575 * has a corresponding `<link rel="preconnect">` tag in the `document.head`. 18576 * 18577 * Note: this is a dev-mode only class, which should not appear in prod bundles, 18578 * thus there is no `ngDevMode` use in the code. 18579 */ 18580 18581class PreconnectLinkChecker { 18582 constructor() { 18583 this.document = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(DOCUMENT); 18584 /** 18585 * Set of <link rel="preconnect"> tags found on this page. 18586 * The `null` value indicates that there was no DOM query operation performed. 18587 */ 18588 18589 this.preconnectLinks = null; 18590 /* 18591 * Keep track of all already seen origin URLs to avoid repeating the same check. 18592 */ 18593 18594 this.alreadySeen = new Set(); 18595 this.window = null; 18596 this.blocklist = new Set(INTERNAL_PRECONNECT_CHECK_BLOCKLIST); 18597 assertDevMode('preconnect link checker'); 18598 const win = this.document.defaultView; 18599 18600 if (typeof win !== 'undefined') { 18601 this.window = win; 18602 } 18603 18604 const blocklist = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(PRECONNECT_CHECK_BLOCKLIST, { 18605 optional: true 18606 }); 18607 18608 if (blocklist) { 18609 this.populateBlocklist(blocklist); 18610 } 18611 } 18612 18613 populateBlocklist(origins) { 18614 if (Array.isArray(origins)) { 18615 deepForEach(origins, origin => { 18616 this.blocklist.add(extractHostname(origin)); 18617 }); 18618 } else { 18619 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2957 18620 /* RuntimeErrorCode.INVALID_PRECONNECT_CHECK_BLOCKLIST */ 18621 , `The blocklist for the preconnect check was not provided as an array. ` + `Check that the \`PRECONNECT_CHECK_BLOCKLIST\` token is configured as a \`multi: true\` provider.`); 18622 } 18623 } 18624 /** 18625 * Checks that a preconnect resource hint exists in the head fo rthe 18626 * given src. 18627 * 18628 * @param rewrittenSrc src formatted with loader 18629 * @param originalNgSrc ngSrc value 18630 */ 18631 18632 18633 assertPreconnect(rewrittenSrc, originalNgSrc) { 18634 if (!this.window) return; 18635 const imgUrl = getUrl(rewrittenSrc, this.window); 18636 if (this.blocklist.has(imgUrl.hostname) || this.alreadySeen.has(imgUrl.origin)) return; // Register this origin as seen, so we don't check it again later. 18637 18638 this.alreadySeen.add(imgUrl.origin); 18639 18640 if (!this.preconnectLinks) { 18641 // Note: we query for preconnect links only *once* and cache the results 18642 // for the entire lifespan of an application, since it's unlikely that the 18643 // list would change frequently. This allows to make sure there are no 18644 // performance implications of making extra DOM lookups for each image. 18645 this.preconnectLinks = this.queryPreconnectLinks(); 18646 } 18647 18648 if (!this.preconnectLinks.has(imgUrl.origin)) { 18649 console.warn((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵformatRuntimeError"])(2956 18650 /* RuntimeErrorCode.PRIORITY_IMG_MISSING_PRECONNECT_TAG */ 18651 , `${imgDirectiveDetails(originalNgSrc)} there is no preconnect tag present for this ` + `image. Preconnecting to the origin(s) that serve priority images ensures that these ` + `images are delivered as soon as possible. To fix this, please add the following ` + `element into the <head>
18651 of the document:\n` + ` <link rel="preconnect" href="${imgUrl.origin}">`)); 18652 } 18653 } 18654 18655 queryPreconnectLinks() { 18656 const preconnectUrls = new Set(); 18657 const selector = 'link[rel=preconnect]'; 18658 const links = Array.from(this.document.querySelectorAll(selector)); 18659 18660 for (let link of links) { 18661 const url = getUrl(link.href, this.window); 18662 preconnectUrls.add(url.origin); 18663 } 18664 18665 return preconnectUrls; 18666 } 18667 18668 ngOnDestroy() { 18669 this.preconnectLinks?.clear(); 18670 this.alreadySeen.clear(); 18671 } 18672 18673} 18674 18675PreconnectLinkChecker.ɵfac = function PreconnectLinkChecker_Factory(t) { 18676 return new (t || PreconnectLinkChecker)(); 18677}; 18678 18679PreconnectLinkChecker.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 18680 token: PreconnectLinkChecker, 18681 factory: PreconnectLinkChecker.ɵfac, 18682 providedIn: 'root' 18683}); 18684 18685(function () { 18686 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](PreconnectLinkChecker, [{ 18687 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 18688 args: [{ 18689 providedIn: 'root' 18690 }] 18691 }], function () { 18692 return []; 18693 }, null); 18694})(); 18695/** 18696 * Invokes a callback for each element in the array. Also invokes a callback 18697 * recursively for each nested array. 18698 */ 18699 18700 18701function deepForEach(input, fn) { 18702 for (let value of input) { 18703 Array.isArray(value) ? deepForEach(value, fn) : fn(value); 18704 } 18705} 18706/** 18707 * @license 18708 * Copyright Google LLC All Rights Reserved. 18709 * 18710 * Use of this source code is governed by an MIT-style license that can be 18711 * found in the LICENSE file at https://angular.io/license 18712 */ 18713 18714/** 18715 * Noop image loader that does no transformation to the original src and just returns it as is. 18716 * This loader is used as a default one if more specific logic is not provided in an app config. 18717 * 18718 * @see `ImageLoader` 18719 * @see `NgOptimizedImage` 18720 */ 18721 18722 18723const noopImageLoader = config => config.src; 18724/** 18725 * Injection token that configures the image loader function. 18726 * 18727 * @see `ImageLoader` 18728 * @see `NgOptimizedImage` 18729 * @publicApi 18730 * @developerPreview 18731 */ 18732 18733 18734const IMAGE_LOADER = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('ImageLoader', { 18735 providedIn: 'root', 18736 factory: () => noopImageLoader 18737}); 18738/** 18739 * Internal helper function that makes it easier to introduce custom image loaders for the 18740 * `NgOptimizedImage` directive. It is enough to specify a URL builder function to obtain full DI 18741 * configuration for a given loader: a DI token corresponding to the actual loader function, plus DI 18742 * tokens managing preconnect check functionality. 18743 * @param buildUrlFn a function returning a full URL based on loader's configuration 18744 * @param exampleUrls example of full URLs for a given loader (used in error messages) 18745 * @returns a set of DI providers corresponding to the configured image loader 18746 */ 18747 18748function createImageLoader(buildUrlFn, exampleUrls) { 18749 return function provideImageLoader(path, options = { 18750 ensurePreconnect: true 18751 }) { 18752 if (!isValidPath(path)) { 18753 throwInvalidPathError(path, exampleUrls || []); 18754 } // The trailing / is stripped (if provided) to make URL construction (concatenation) easier in 18755 // the individual loader functions. 18756 18757 18758 path = normalizePath(path); 18759 18760 const loaderFn = config => { 18761 if (isAbsoluteUrl(config.src)) { 18762 // Image loader functions expect an image file name (e.g. `my-image.png`) 18763 // or a relative path + a file name (e.g. `/a/b/c/my-image.png`) as an input, 18764 // so the final absolute URL can be constructed. 18765 // When an absolute URL is provided instead - the loader can not 18766 // build a final URL, thus the error is thrown to indicate that. 18767 throwUnexpectedAbsoluteUrlError(path, config.src); 18768 } 18769 18770 return buildUrlFn(path, { ...config, 18771 src: normalizeSrc(config.src) 18772 }); 18773 }; 18774 18775 const providers = [{ 18776 provide: IMAGE_LOADER, 18777 useValue: loaderFn 18778 }]; 18779 18780 if (ngDevMode && options.ensurePreconnect === false) { 18781 providers.push({ 18782 provide: PRECONNECT_CHECK_BLOCKLIST, 18783 useValue: [path], 18784 multi: true 18785 }); 18786 } 18787 18788 return providers; 18789 }; 18790} 18791 18792function throwInvalidPathError(path, exampleUrls) { 18793 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2959 18794 /* RuntimeErrorCode.INVALID_LOADER_ARGUMENTS */
18795 , ngDevMode && `Image loader has detected an invalid path (\`${path}\`). ` + `To fix this, supply a path using one of the following formats: ${exampleUrls.join(' or ')}`); 18796} 18797 18798function throwUnexpectedAbsoluteUrlError(path, url) { 18799 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2959 18800 /* RuntimeErrorCode.INVALID_LOADER_ARGUMENTS */ 18801 , ngDevMode && `Image loader has detected a \`<img>\` tag with an invalid \`ngSrc\` attribute: ${url}. ` + `This image loader expects \`ngSrc\` to be a relative URL - ` + `however the provided value is an absolute URL. ` + `To fix this, provide \`ngSrc\` as a path relative to the base URL ` + `configured for this loader (\`${path}\`).`); 18802} 18803/** 18804 * @license 18805 * Copyright Google LLC All Rights Reserved. 18806 * 18807 * Use of this source code is governed by an MIT-style license that can be 18808 * found in the LICENSE file at https://angular.io/license 18809 */ 18810 18811/** 18812 * Function that generates an ImageLoader for [Cloudflare Image 18813 * Resizing](https://developers.cloudflare.com/images/image-resizing/) and turns it into an Angular 18814 * provider. Note: Cloudflare has multiple image products - this provider is specifically for 18815 * Cloudflare Image Resizing; it will not work with Cloudflare Images or Cloudflare Polish. 18816 * 18817 * @param path Your domain name, e.g. https://mysite.com 18818 * @param options An object with extra configuration: 18819 * - `ensurePreconnect`: boolean flag indicating whether the NgOptimizedImage directive 18820 * should verify that there is a corresponding `<link rel="preconnect">` 18821 * present in the document's `<head>`. 18822 * @returns Provider that provides an ImageLoader function 18823 * 18824 * @publicApi 18825 * @developerPreview 18826 */ 18827 18828 18829const provideCloudflareLoader = createImageLoader(createCloudflareUrl, ngDevMode ? ['https://<ZONE>/cdn-cgi/image/<OPTIONS>/<SOURCE-IMAGE>'] : undefined); 18830 18831function createCloudflareUrl(path, config) { 18832 let params = `format=auto`; 18833 18834 if (config.width) { 18835 params += `,width=${config.width}`; 18836 } // Cloudflare image URLs format: 18837 // https://developers.cloudflare.com/images/image-resizing/url-format/ 18838 18839 18840 return `${path}/cdn-cgi/image/${params}/${config.src}`; 18841} 18842/** 18843 * @license 18844 * Copyright Google LLC All Rights Reserved. 18845 * 18846 * Use of this source code is governed by an MIT-style license that can be 18847 * found in the LICENSE file at https://angular.io/license 18848 */ 18849 18850/** 18851 * Function that generates an ImageLoader for Cloudinary and turns it into an Angular provider. 18852 * 18853 * @param path Base URL of your Cloudinary images 18854 * This URL should match one of the following formats: 18855 * https://res.cloudinary.com/mysite 18856 * https://mysite.cloudinary.com 18857 * https://subdomain.mysite.com 18858 * @param options An object with extra configuration: 18859 * - `ensurePreconnect`: boolean flag indicating whether the NgOptimizedImage directive 18860 * should verify that there is a corresponding `<link rel="preconnect">` 18861 * present in the document's `<head>`. 18862 * @returns Set of providers to configure the Cloudinary loader. 18863 * 18864 * @publicApi 18865 * @developerPreview 18866 */ 18867 18868 18869const provideCloudinaryLoader = createImageLoader(createCloudinaryUrl, ngDevMode ? ['https://res.cloudinary.com/mysite', 'https://mysite.cloudinary.com', 'https://subdomain.mysite.com'] : undefined); 18870 18871function createCloudinaryUrl(path, config) { 18872 // Cloudinary image URLformat: 18873 // https://cloudinary.com/documentation/image_transformations#transformation_url_structure 18874 // Example of a Cloudinary image URL: 18875 // https://res.cloudinary.com/mysite/image/upload/c_scale,f_auto,q_auto,w_600/marketing/tile-topics-m.png 18876 let params = `f_auto,q_auto`; // sets image format and quality to "auto" 18877 18878 if (config.width) { 18879 params += `,w_${config.width}`; 18880 } 18881 18882 return `${path}/image/upload/${params}/${config.src}`; 18883} 18884/** 18885 * @license 18886 * Copyright Google LLC All Rights Reserved. 18887 * 18888 * Use of this source code is governed by an MIT-style license that can be 18889 * found in the LICENSE file at https://angular.io/license 18890 */ 18891 18892/** 18893 * Function that generates an ImageLoader for ImageKit and turns it into an Angular provider. 18894 * 18895 * @param path Base URL of your ImageKit images 18896 * This URL should match one of the following formats: 18897 * https://ik.imagekit.io/myaccount 18898 * https://subdomain.mysite.com 18899 * @param options An object with extra configuration: 18900 * - `ensurePreconnect`: boolean flag indicating whether the NgOptimizedImage directive 18901 * should verify that there is a corresponding `<link rel="prec
18901onnect">` 18902 * present in the document's `<head>`. 18903 * @returns Set of providers to configure the ImageKit loader. 18904 * 18905 * @publicApi 18906 * @developerPreview 18907 */ 18908 18909 18910const provideImageKitLoader = createImageLoader(createImagekitUrl, ngDevMode ? ['https://ik.imagekit.io/mysite', 'https://subdomain.mysite.com'] : undefined); 18911 18912function createImagekitUrl(path, config) { 18913 // Example of an ImageKit image URL: 18914 // https://ik.imagekit.io/demo/tr:w-300,h-300/medium_cafe_B1iTdD0C.jpg 18915 let params = `tr:q-auto`; // applies the "auto quality" transformation 18916 18917 if (config.width) { 18918 params += `,w-${config.width}`; 18919 } 18920 18921 return `${path}/${params}/${config.src}`; 18922} 18923/** 18924 * @license 18925 * Copyright Google LLC All Rights Reserved. 18926 * 18927 * Use of this source code is governed by an MIT-style license that can be 18928 * found in the LICENSE file at https://angular.io/license 18929 */ 18930 18931/** 18932 * Function that generates an ImageLoader for Imgix and turns it into an Angular provider. 18933 * 18934 * @param path path to the desired Imgix origin, 18935 * e.g. https://somepath.imgix.net or https://images.mysite.com 18936 * @param options An object with extra configuration: 18937 * - `ensurePreconnect`: boolean flag indicating whether the NgOptimizedImage directive 18938 * should verify that there is a corresponding `<link rel="preconnect">` 18939 * present in the document's `<head>`. 18940 * @returns Set of providers to configure the Imgix loader. 18941 * 18942 * @publicApi 18943 * @developerPreview 18944 */ 18945 18946 18947const provideImgixLoader = createImageLoader(createImgixUrl, ngDevMode ? ['https://somepath.imgix.net/'] : undefined); 18948 18949function createImgixUrl(path, config) { 18950 const url = new URL(`${path}/${config.src}`); // This setting ensures the smallest allowable format is set. 18951 18952 url.searchParams.set('auto', 'format'); 18953 18954 if (config.width) { 18955 url.searchParams.set('w', config.width.toString()); 18956 } 18957 18958 return url.href; 18959} 18960/** 18961 * @license 18962 * Copyright Google LLC All Rights Reserved. 18963 * 18964 * Use of this source code is governed by an MIT-style license that can be 18965 * found in the LICENSE file at https://angular.io/license 18966 */ 18967 18968/** 18969 * Observer that detects whether an image with `NgOptimizedImage` 18970 * is treated as a Largest Contentful Paint (LCP) element. If so, 18971 * asserts that the image has the `priority` attribute. 18972 * 18973 * Note: this is a dev-mode only class and it does not appear in prod bundles, 18974 * thus there is no `ngDevMode` use in the code. 18975 * 18976 * Based on https://web.dev/lcp/#measure-lcp-in-javascript. 18977 */ 18978 18979 18980class LCPImageObserver { 18981 constructor() { 18982 // Map of full image URLs -> original `ngSrc` values. 18983 this.images = new Map(); // Keep track of images for which `console.warn` was produced. 18984 18985 this.alreadyWarned = new Set(); 18986 this.window = null; 18987 this.observer = null; 18988 assertDevMode('LCP checker'); 18989 const win = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(DOCUMENT).defaultView; 18990 18991 if (typeof win !== 'undefined' && typeof PerformanceObserver !== 'undefined') { 18992 this.window = win; 18993 this.observer = this.initPerformanceObserver(); 18994 } 18995 } 18996 /** 18997 * Inits PerformanceObserver and subscribes to LCP events. 18998 * Based on https://web.dev/lcp/#measure-lcp-in-javascript 18999 */ 19000 19001 19002 initPerformanceObserver() { 19003 const observer = new PerformanceObserver(entryList => { 19004 const entries = entryList.getEntries(); 19005 if (entries.length === 0) return; // We use the latest entry produced by the `PerformanceObserver` as the best 19006 // signal on which element is actually an LCP one. As an example, the first image to load on 19007 // a page, by virtue of being the only thing on the page so far, is often a LCP candidate 19008 // and gets reported by PerformanceObserver, but isn't necessarily the LCP element. 19009 19010 const lcpElement = entries[entries.length - 1]; // Cast to `any` due to missing `element` on the `LargestContentfulPaint` type of entry. 19011 // See https://developer.mozilla.org/en-US/docs/Web/API/LargestContentfulPaint 19012 19013 const imgSrc = lcpElement.element?.src ?? ''; // Exclude `data:` and `blob:` URLs, since they are not supported by the directive. 19014 19015 if (imgSrc.startsWith('data:') || imgSrc.startsWith('blob:')) return; 19016 const imgNgSrc = this.images.get(imgSrc); 19017 19018 if (imgNgSrc && !this.alreadyWarned.has(imgSrc)) { 19019 this.alreadyWarned.add(imgSrc); 19020 logMissingPriorityWarning(imgSrc); 19021 } 19022 }); 19023 observer.observe({ 19024 type: 'largest-contentful-paint', 19025 buffered: true 19026 }); 19027 return observer; 19028 } 19029 19030 registerImage(rewrittenSrc, originalNgSrc) { 19031 if (!this.observer) return; 19032 this.images.set(getUrl(rewrittenSrc, this.window).href, originalNgSrc); 19033 } 19034 19035 unregisterImage(rewrittenSrc) { 19036 if (!this.observer) return; 19037 this.images.delete(getUrl(rewrittenSrc, this.window).href); 19038 } 19039 19040 ngOnDestroy() { 19041 if (!this.observer) return; 19042 this.observer.disconnect(); 19043 this.images.clear(); 19044 this.alreadyWarned.clear(); 19045 } 19046 19047} 19048 19049LCPImageObserver.ɵfac = function LCPImageObserver_Factory(t) { 19050 return new (t || LCPImageObserver)(); 19051}; 19052 19053LCPImageObserver.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 19054 token: LCPImageObserver, 19055 factory: LCPImageObserver.ɵfac, 19056 providedIn: 'root' 19057}); 19058 19059(function () { 19060 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](LCPImageObserver, [{ 19061 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 19062 args: [{ 19063 providedIn: 'root' 19064 }] 19065 }], function () { 19066 return []; 19067 }, null); 19068})(); 19069 19070function logMissingPriorityWarning(ngSrc) { 19071 const directiveDetails = imgDirectiveDetails(ngSrc); 19072 console.warn((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵformatRuntimeError"])(2955 19073 /* RuntimeErrorCode.LCP_IMG_MISSING_PRIORITY */ 19074 , `${directiveDetails} this image is the Largest Contentful Paint (LCP) ` + `element but was not marked "priority". This image should be marked ` + `"priority" in order to prioritize its loading. ` + `To fix this, add the "priority" attribute.`)); 19075} 19076/** 19077 * @license 19078 * Copyright Google LLC All Rights Reserved. 19079 * 19080 * Use of this source code is governed by an MIT-style license that can be 19081 * found in the LICENSE file at https://angular.io/license 19082 */ 19083 19084/** 19085 * When a Base64-encoded image is passed as an input to the `NgOptimizedImage` directive, 19086 * an error is thrown. The image content (as a string) might be very long, thus making
19087 * it hard to read an error message if the entire string is included. This const defines 19088 * the number of characters that should be included into the error message. The rest 19089 * of the content is truncated. 19090 */ 19091 19092 19093const BASE64_IMG_MAX_LENGTH_IN_ERROR = 50; 19094/** 19095 * RegExpr to determine whether a src in a srcset is using width descriptors. 19096 * Should match something like: "100w, 200w". 19097 */ 19098 19099const VALID_WIDTH_DESCRIPTOR_SRCSET = /^((\s*\d+w\s*(,|$)){1,})$/; 19100/** 19101 * RegExpr to determine whether a src in a srcset is using density descriptors. 19102 * Should match something like: "1x, 2x, 50x". Also supports decimals like "1.5x, 1.50x". 19103 */ 19104 19105const VALID_DENSITY_DESCRIPTOR_SRCSET = /^((\s*\d+(\.\d+)?x\s*(,|$)){1,})$/; 19106/** 19107 * Srcset values with a density descriptor higher than this value will actively 19108 * throw an error. Such densities are not permitted as they cause image sizes 19109 * to be unreasonably large and slow down LCP. 19110 */ 19111 19112const ABSOLUTE_SRCSET_DENSITY_CAP = 3; 19113/** 19114 * Used only in error message text to communicate best practices, as we will 19115 * only throw based on the slightly more conservative ABSOLUTE_SRCSET_DENSITY_CAP. 19116 */ 19117 19118const RECOMMENDED_SRCSET_DENSITY_CAP = 2; 19119/** 19120 * Used to determine whether two aspect ratios are similar in value. 19121 */ 19122 19123const ASPECT_RATIO_TOLERANCE = .1; 19124/** 19125 * Used to determine whether the image has been requested at an overly 19126 * large size compared to the actual rendered image size (after taking 19127 * into account a typical device pixel ratio). In pixels. 19128 */ 19129 19130const OVERSIZED_IMAGE_TOLERANCE = 1000; 19131/** 19132 * Directive that improves image loading performance by enforcing best practices. 19133 * 19134 * `NgOptimizedImage` ensures that the loading of the Largest Contentful Paint (LCP) image is 19135 * prioritized by: 19136 * - Automatically setting the `fetchpriority` attribute on the `<img>` tag 19137 * - Lazy loading non-priority images by default 19138 * - Asserting that there is a corresponding preconnect link tag in the document head 19139 * 19140 * In addition, the directive: 19141 * - Generates appropriate asset URLs if a corresponding `ImageLoader` function is provided 19142 * - Requires that `width` and `height` are set 19143 * - Warns if `width` or `height` have been set incorrectly 19144 * - Warns if the image will be visually distorted when rendered 19145 * 19146 * @usageNotes 19147 * The `NgOptimizedImage` directive is marked as [standalone](guide/standalone-components) and can 19148 * be imported directly. 19149 * 19150 * Follow the steps below to enable and use the directive: 19151 * 1. Import it into the necessary NgModule or a standalone Component. 19152 * 2. Optionally provide an `ImageLoader` if you use an image hosting service. 19153 * 3. Update the necessary `<img>` tags in templates and replace `src` attributes with `ngSrc`. 19154 * Using a `ngSrc` allows the directive to control when the `src` gets set, which triggers an image 19155 * download. 19156 * 19157 * Step 1: import the `NgOptimizedImage` directive. 19158 * 19159 * ```typescript 19160 * import { NgOptimizedImage } from '@angular/common'; 19161 * 19162 * // Include it into the necessary NgModule 19163 * @NgModule({ 19164 * imports: [NgOptimizedImage], 19165 * }) 19166 * class AppModule {} 19167 * 19168 * // ... or a standalone Component 19169 * @Component({ 19170 * standalone: true 19171 * imports: [NgOptimizedImage], 19172 * }) 19173 * class MyStandaloneComponent {} 19174 * ``` 19175 * 19176 * Step 2: configure a loader. 19177 * 19178 * To use the **default loader**: no additional code changes are necessary. The URL returned by the 19179 * generic loader will always match the value of "src". In other words, this loader applies no 19180 * transformations to the resource URL and the value of the `ngSrc` attribute will be used as is. 19181 * 19182 * To use an existing loader for a **third-party image service**: add the provider factory for your 19183 * chosen service to the `providers` array. In the example below, the Imgix loader is used: 19184 * 19185 * ```typescript 19186 * import {provideImgixLoader} from '@angular/common'; 19187 * 19188 * // Call the function and add the result to the `providers` array: 19189 * providers: [ 19190 * provideImgixLoader("https://my.base.url/"), 19191 * ], 19192 * ``` 19193 * 19194 * The `NgOptimizedImage` directive provides the following functions: 19195 * - `provideCloudflareLoader` 19196 * - `provideCloudinaryLoader` 19197 * - `provideImageKitLoader` 19198 * - `provideImgixLoader` 19199 * 19200 * If you use a different image provider, you can create a custom loader function as described 19201 * below. 19202 * 19203 * To use a **custom loader**: provide your loader function as a value for the `IMAGE_LOADER` DI 19204 * token. 19205 * 19206 * ```typescript 19207 * import {IMAGE_LOADER, ImageLoaderConfig} from '@angular/common'; 19208 * 19209 * // Configure the loader using the `IMAGE_LOADER` token. 19210 * providers: [ 19211 * {
19212 * provide: IMAGE_LOADER, 19213 * useValue: (config: ImageLoaderConfig) => { 19214 * return `https://example.com/${config.src}-${config.width}.jpg}`; 19215 * } 19216 * }, 19217 * ], 19218 * ``` 19219 * 19220 * Step 3: update `<img>` tags in templates to use `ngSrc` instead of `src`. 19221 * 19222 * ``` 19223 * <img ngSrc="logo.png" width="200" height="100"> 19224 * ``` 19225 * 19226 * @publicApi 19227 * @developerPreview 19228 */ 19229 19230class NgOptimizedImage { 19231 constructor() { 19232 this.imageLoader = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(IMAGE_LOADER); 19233 this.renderer = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2); 19234 this.imgElement = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef).nativeElement; 19235 this.injector = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector); // a LCP image observer - should be injected only in the dev mode 19236 19237 this.lcpObserver = ngDevMode ? this.injector.get(LCPImageObserver) : null; 19238 /** 19239 * Calculate the rewritten `src` once and store it. 19240 * This is needed to avoid repetitive calculations and make sure the directive cleanup in the 19241 * `ngOnDestroy` does not rely on the `IMAGE_LOADER` logic (which in turn can rely on some other 19242 * instance that might be already destroyed). 19243 */ 19244 19245 this._renderedSrc = null; 19246 this._priority = false; 19247 } 19248 /** 19249 * Previously, the `rawSrc` attribute was used to activate the directive. 19250 * The attribute was renamed to `ngSrc` and this input just produces an error, 19251 * suggesting to switch to `ngSrc` instead. 19252 * 19253 * This error should be removed in v15. 19254 * 19255 * @nodoc 19256 * @deprecated Use `ngSrc` instead. 19257 */ 19258 19259 19260 set rawSrc(value) { 19261 if (ngDevMode) { 19262 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952 19263 /* RuntimeErrorCode.INVALID_INPUT */ 19264 , `${imgDirectiveDetails(value, false)} the \`rawSrc\` attribute was used ` + `to activate the directive. Newer version of the directive uses the \`ngSrc\` ` + `attribute instead. Please replace \`rawSrc\` with \`ngSrc\` and ` + `\`rawSrcset\` with \`ngSrcset\` attributes in the template to ` + `enable image optimizations.`); 19265 } 19266 } 19267 /** 19268 * The intrinsic width of the image in pixels. 19269 */ 19270 19271 19272 set width(value) { 19273 ngDevMode && assertGreaterThanZero(this, value, 'width'); 19274 this._width = inputToInteger(value); 19275 } 19276 19277 get width() { 19278 return this._width; 19279 } 19280 /** 19281 * The intrinsic height of the image in pixels. 19282 */ 19283 19284 19285 set height(value) { 19286 ngDevMode && assertGreaterThanZero(this, value, 'height'); 19287 this._height = inputToInteger(value); 19288 } 19289 19290 get height() { 19291 return this._height; 19292 } 19293 /** 19294 * Indicates whether this image should have a high priority. 19295 */ 19296 19297 19298 set priority(value) { 19299 this._priority = inputToBoolean(value); 19300 } 19301 19302 get priority() { 19303 return this._priority; 19304 } 19305 19306 ngOnInit() { 19307 if (ngDevMode) { 19308 assertNonEmptyInput(this, 'ngSrc', this.ngSrc); 19309 assertValidNgSrcset(this, this.ngSrcset); 19310 assertNoConflictingSrc(this); 19311 assertNoConflictingSrcset(this); 19312 assertNotBase64Image(this); 19313 assertNotBlobUrl(this); 19314 assertNonEmptyWidthAndHeight(this); 19315 assertValidLoadingInput(this); 19316 assertNoImageDistortion(this, this.imgElement, this.renderer); 19317 19318 if (this.priority) { 19319 const checker = this.injector.get(PreconnectLinkChecker); 19320 checker.assertPreconnect(this.getRewrittenSrc(), this.ngSrc); 19321 } else { 19322 // Monitor whether an image is an LCP element only in case 19323 // the `priority` attribute is missing. Otherwise, an image 19324 // has the necessary settings and no extra checks are required. 19325 if (this.lcpObserver !== null) { 19326 const ngZone = this.injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone); 19327 ngZone.runOutsideAngular(() => { 19328 this.lcpObserver.registerImage(this.getRewrittenSrc(), this.ngSrc); 19329 }); 19330 } 19331 } 19332 } 19333 19334 this.setHostAttributes(); 19335 } 19336 19337 setHostAttributes() { 19338 // Must set width/height explicitly in case they are bound (in which case they will 19339 // only be reflected and not found by the browser) 19340 this.setHostAttribute('width', this.width.toString()); 19341 this.setHostAttribute('height', this.height.toString()); 19342 this.setHostAttribute('loading', this.getLoadingBehavior()); 19343 this.setHostAttribute('fetchpriority', this.getFetchPriority()); // The `src` and `srcset` attributes should be set last since other attributes 19344 // could affect the image's loading behavior. 19345 19346 this.setHostAttribute('src', this.getRewrittenSrc()); 19347 19348 if (this.ngSrcset) { 19349 this.setHostAttribute('srcset', this.getRewrittenSrcset()); 19350 } 19351 } 19352 19353 ngOnChanges(changes) { 19354 if (ngDevMode) { 19355 assertNoPostInitInputChange(this, changes, ['ngSrc', 'ngSrcset', 'width', 'height', 'priority']); 19356 } 19357 } 19358 19359 getLoadingBehavior() { 19360 if (!this.priority && this.loading !== undefined) { 19361 return this.loading; 19362 } 19363 19364 return this.priority ? 'eager' : 'lazy'; 19365 } 19366 19367 getFetchPriority() { 19368 return this.priority ? 'high' : 'auto'; 19369 } 19370 19371 getRewrittenSrc() { 19372 // ImageLoaderConfig supports setting a width property. However, we're not setting width here 19373 // because if the developer uses rendered width instead of intrinsic width in the HTML width 19374 // attribute, the image requested may be too small for 2x+ screens. 19375 if (!this._renderedSrc) { 19376 const imgConfig = { 19377 src: this.ngSrc 19378 }; // Cache calculated image src to reuse it later in the code. 19379 19380 this._renderedSrc = this.imageLoader(imgConfig); 19381 } 19382 19383 return this._renderedSrc; 19384 } 19385 19386 getRewrittenSrcset() { 19387 const widthSrcSet = VALID_WIDTH_DESCRIPTOR_SRCSET.test(this.ngSrcset); 19388 const finalSrcs = this.ngSrcset.split(',').filter(src => src !== '').map(srcStr => { 19389 srcStr = srcStr.trim(); 19390 const width = widthSrcSet ? parseFloat(srcStr) : parseFloat(srcStr) * this.width; 19391 return `${this.imageLoader({ 19392 src: this.ngSrc, 19393 width 19394 })} ${srcStr}`; 19395 }); 19396 return finalSrcs.join(', '); 19397 } 19398 19399 ngOnDestroy() { 19400 if (ngDevMode) { 19401 if (!this.priority && this._renderedSrc !== null && this.lcpObserver !== null) { 19402 this.lcpObserver.unregisterImage(this._renderedSrc); 19403 } 19404 } 19405 } 19406 19407 setHostAttribute(name, value) { 19408 this.renderer.setAttribute(this.imgElement, name, value); 19409 } 19410 19411} 19412 19413NgOptimizedImage.ɵfac = function NgOptimizedImage_Factory(t) { 19414 return new (t || NgOptimizedImage)(); 19415}; 19416 19417NgOptimizedImage.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 19418 type: NgOptimizedImage, 19419 selectors: [["img", "ngSrc", ""], ["img", "rawSrc", ""]], 19420 inputs: { 19421 rawSrc: "rawSrc", 19422 ngSrc: "ngSrc", 19423 ngSrcset: "ngSrcset", 19424 width: "width", 19425 height: "height", 19426 loading: "loading", 19427 priority: "priority", 19428 src: "src", 19429 srcset: "srcset" 19430 }, 19431 standalone: true, 19432 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]] 19433}); 19434 19435(function () { 19436 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgOptimizedImage, [{ 19437 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 19438 args: [{ 19439 standalone: true, 19440 selector: 'img[ngSrc],img[rawSrc]' 19441 }] 19442 }], null, { 19443 rawSrc: [{ 19444 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 19445 }], 19446 ngSrc: [{ 19447 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 19448 }], 19449 ngSrcset: [{ 19450 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 19451 }], 19452 width: [{ 19453 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 19454 }], 19455 height: [{ 19456 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 19457 }], 19458 loading: [{ 19459 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 19460 }], 19461 priority: [{ 19462 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 19463 }], 19464 src: [{ 19465 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 19466 }], 19467 srcset: [{ 19468 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 19469 }] 19470 }); 19471})(); 19472/***** Helpers *****/ 19473 19474/** 19475 * Convert input value to integer. 19476 */ 19477 19478 19479function inputToInteger(value) { 19480 return typeof value === 'string' ? parseInt(value, 10) : value; 19481} 19482/** 19483 * Convert input value to boolean. 19484 */ 19485 19486 19487function inputToBoolean(value) { 19488 return value != null && `${value}` !== 'false'; 19489} 19490/***** Assert functions *****/ 19491 19492/** 19493 * Verifies that there is no `src` set on a host element. 19494 */ 19495 19496 19497function assertNoConflictingSrc(dir) { 19498 if (dir.src) { 19499 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2950 19500 /* RuntimeErrorCode.UNEXPECTED_SRC_ATTR */ 19501 , `${imgDirectiveDetails(dir.ngSrc)} both \`src\` and \`ngSrc\` have been set. ` + `Supplying both of these attributes breaks lazy loading. ` + `The NgOptimizedImage directive sets \`src\` itself based on the value of \`ngSrc\`. ` + `To fix this, please remove the \`src\` attribute.`); 19502 } 19503} 19504/** 19505 * Verifies that there is no `srcset` set on a host element. 19506 */ 19507 19508 19509function assertNoConflictingSrcset(dir) { 19510 if (dir.srcset) { 19511 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2951 19512 /* RuntimeErrorCode.UNEXPECTED_SRCSET_ATTR */ 19513 , `${imgDirectiveDetails(dir.ngSrc)} both \`srcset\` and \`ngSrcset\` have been set. ` + `Supplying both of these attributes breaks lazy loading. ` + `The NgOptimizedImage directive sets \`srcset\` itself based on the value of ` + `\`ngSrcset\`. To fix this, please remove the \`srcset\` attribute.`); 19514 } 19515} 19516/** 19517 * Verifies that the `ngSrc` is not a Base64-encoded image. 19518 */ 19519 19520 19521function assertNotBase64Image(dir) { 19522 let ngSrc = dir.ngSrc.trim(); 19523 19524 if (ngSrc.startsWith('data:')) { 19525 if (ngSrc.length > BASE64_IMG_MAX_LENGTH_IN_ERROR) { 19526 ngSrc = ngSrc.substring(0, BASE64_IMG_MAX_LENGTH_IN_ERROR) + '...'; 19527 } 19528 19529 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952 19530 /* RuntimeErrorCode.INVALID_INPUT */ 19531 , `${imgDirectiveDetails(dir.ngSrc, false)} \`ngSrc\` is a Base64-encoded string ` + `(${ngSrc}). NgOptimizedImage does not support Base64-encoded strings. ` + `To fix this, disable the NgOptimizedImage directive for this element ` + `by removing \`ngSrc\` and using a standard \`src\` attribute instead.`); 19532 } 19533} 19534/** 19535 * Verifies that the `ngSrc` is not a Blob URL. 19536 */ 19537 19538 19539function assertNotBlobUrl(dir) { 19540 const ngSrc = dir.ngSrc.trim(); 19541 19542 if (ngSrc.startsWith('blob:')) { 19543 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952 19544 /* RuntimeErrorCode.INVALID_INPUT */ 19545 , `${imgDirectiveDetails(dir.ngSrc)} \`ngSrc\` was set to a blob URL (${ngSrc}). ` + `Blob URLs are not supported by the NgOptimizedImage directive. ` + `To fix this, disable the NgOptimizedImage directive for this element ` + `by removing \`ngSrc\` and using a regular \`src\` attribute instead.`); 19546 } 19547} 19548/** 19549 * Verifies that the input is set to a non-empty string. 19550 */ 19551 19552 19553function assertNonEmptyInput(dir, name, value) { 19554 const isString = typeof value === 'string'; 19555 const isEmptyString = isString && value.trim() === ''; 19556 19557 if (!isString || isEmptyString) { 19558 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952 19559 /* RuntimeErrorCode.INVALID_INPUT */ 19560 , `${imgDirectiveDetails(dir.ngSrc)} \`${name}
19560\` has an invalid value ` + `(\`${value}\`). To fix this, change the value to a non-empty string.`); 19561 } 19562} 19563/** 19564 * Verifies that the `ngSrcset` is in a valid format, e.g. "100w, 200w" or "1x, 2x". 19565 */ 19566 19567 19568function assertValidNgSrcset(dir, value) { 19569 if (value == null) return; 19570 assertNonEmptyInput(dir, 'ngSrcset', value); 19571 const stringVal = value; 19572 const isValidWidthDescriptor = VALID_WIDTH_DESCRIPTOR_SRCSET.test(stringVal); 19573 const isValidDensityDescriptor = VALID_DENSITY_DESCRIPTOR_SRCSET.test(stringVal); 19574 19575 if (isValidDensityDescriptor) { 19576 assertUnderDensityCap(dir, stringVal); 19577 } 19578 19579 const isValidSrcset = isValidWidthDescriptor || isValidDensityDescriptor; 19580 19581 if (!isValidSrcset) { 19582 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952 19583 /* RuntimeErrorCode.INVALID_INPUT */ 19584 , `${imgDirectiveDetails(dir.ngSrc)} \`ngSrcset\` has an invalid value (\`${value}\`). ` + `To fix this, supply \`ngSrcset\` using a comma-separated list of one or more width ` + `descriptors (e.g. "100w, 200w") or density descriptors (e.g. "1x, 2x").`); 19585 } 19586} 19587 19588function assertUnderDensityCap(dir, value) { 19589 const underDensityCap = value.split(',').every(num => num === '' || parseFloat(num) <= ABSOLUTE_SRCSET_DENSITY_CAP); 19590 19591 if (!underDensityCap) { 19592 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952 19593 /* RuntimeErrorCode.INVALID_INPUT */ 19594 , `${imgDirectiveDetails(dir.ngSrc)} the \`ngSrcset\` contains an unsupported image density:` + `\`${value}\`. NgOptimizedImage generally recommends a max image density of ` + `${RECOMMENDED_SRCSET_DENSITY_CAP}x but supports image densities up to ` + `${ABSOLUTE_SRCSET_DENSITY_CAP}x. The human eye cannot distinguish between image densities ` + `greater than ${RECOMMENDED_SRCSET_DENSITY_CAP}x - which makes them unnecessary for ` + `most use cases. Images that will be pinch-zoomed are typically the primary use case for ` + `${ABSOLUTE_SRCSET_DENSITY_CAP}x images. Please remove the high density descriptor and try again.`); 19595 } 19596} 19597/** 19598 * Creates a `RuntimeError` instance to represent a situation when an input is set after 19599 * the directive has initialized. 19600 */ 19601 19602 19603function postInitInputChangeError(dir, inputName) { 19604 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2953 19605 /* RuntimeErrorCode.UNEXPECTED_INPUT_CHANGE */ 19606 , `${imgDirectiveDetails(dir.ngSrc)} \`${inputName}\` was updated after initialization. ` + `The NgOptimizedImage directive will not react to this input change. ` + `To fix this, switch \`${inputName}\` a static value or wrap the image element ` + `in an *ngIf that is gated on the necessary value.`); 19607} 19608/** 19609 * Verify that none of the listed inputs has changed. 19610 */ 19611 19612 19613function assertNoPostInitInputChange(dir, changes, inputs) { 19614 inputs.forEach(input => { 19615 const isUpdated = changes.hasOwnProperty(input); 19616 19617 if (isUpdated && !changes[input].isFirstChange()) { 19618 if (input === 'ngSrc') { 19619 // When the `ngSrc` input changes, we detect that only in the
19620 // `ngOnChanges` hook, thus the `ngSrc` is already set. We use 19621 // `ngSrc` in the error message, so we use a previous value, but 19622 // not the updated one in it. 19623 dir = { 19624 ngSrc: changes[input].previousValue 19625 }; 19626 } 19627 19628 throw postInitInputChangeError(dir, input); 19629 } 19630 }); 19631} 19632/** 19633 * Verifies that a specified input is a number greater than 0. 19634 */ 19635 19636 19637function assertGreaterThanZero(dir, inputValue, inputName) { 19638 const validNumber = typeof inputValue === 'number' && inputValue > 0; 19639 const validString = typeof inputValue === 'string' && /^\d+$/.test(inputValue.trim()) && parseInt(inputValue) > 0; 19640 19641 if (!validNumber && !validString) { 19642 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952 19643 /* RuntimeErrorCode.INVALID_INPUT */ 19644 , `${imgDirectiveDetails(dir.ngSrc)} \`${inputName}\` has an invalid value ` + `(\`${inputValue}\`). To fix this, provide \`${inputName}\` ` + `as a number greater than 0.`); 19645 } 19646} 19647/** 19648 * Verifies that the rendered image is not visually distorted. Effectively this is checking: 19649 * - Whether the "width" and "height" attributes reflect the actual dimensions of the image. 19650 * - Whether image styling is "correct" (see below for a longer explanation). 19651 */ 19652 19653 19654function assertNoImageDistortion(dir, img, renderer) { 19655 const removeListenerFn = renderer.listen(img, 'load', () => { 19656 removeListenerFn(); // TODO: `clientWidth`, `clientHeight`, `naturalWidth` and `naturalHeight` 19657 // are typed as number, but we run `parseFloat` (which accepts strings only). 19658 // Verify whether `parseFloat` is needed in the cases below. 19659 19660 const renderedWidth = parseFloat(img.clientWidth); 19661 const renderedHeight = parseFloat(img.clientHeight); 19662 const renderedAspectRatio = renderedWidth / renderedHeight; 19663 const nonZeroRenderedDimensions = renderedWidth !== 0 && renderedHeight !== 0; 19664 const intrinsicWidth = parseFloat(img.naturalWidth); 19665 const intrinsicHeight = parseFloat(img.naturalHeight); 19666 const intrinsicAspectRatio = intrinsicWidth / intrinsicHeight; 19667 const suppliedWidth = dir.width; 19668 const suppliedHeight = dir.height; 19669 const suppliedAspectRatio = suppliedWidth / suppliedHeight; // Tolerance is used to account for the impact of subpixel rendering. 19670 // Due to subpixel rendering, the rendered, intrinsic, and supplied 19671 // aspect ratios of a correctly configured image may not exactly match. 19672 // For example, a `width=4030 height=3020` image might have a rendered 19673 // size of "1062w, 796.48h". (An aspect ratio of 1.334... vs. 1.333...) 19674 19675 const inaccurateDimensions = Math.abs(suppliedAspectRatio - intrinsicAspectRatio) > ASPECT_RATIO_TOLERANCE; 19676 const stylingDistortion = nonZeroRenderedDimensions && Math.abs(intrinsicAspectRatio - renderedAspectRatio) > ASPECT_RATIO_TOLERANCE; 19677 19678 if (inaccurateDimensions) { 19679 console.warn((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵformatRuntimeError"])(2952 19680 /* RuntimeErrorCode.INVALID_INPUT */ 19681 , `${imgDirectiveDetails(dir.ngSrc)} the aspect ratio of the image does not match ` + `the aspect ratio indicated by the width and height attributes. ` + `\nIntrinsic image size: ${intrinsicWidth}w x ${intrinsicHeight}h ` + `(aspect-ratio: ${intrinsicAspectRatio}). \nSupplied width and height attributes: ` + `${suppliedWidth}w x ${suppliedHeight}h (aspect-ratio: ${suppliedAspectRatio}). ` + `\nTo fix this, update the width and height attributes.`)); 19682 } else if (stylingDistortion) { 19683 console.warn((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵformatRuntimeError"])(2952 19684 /* RuntimeErrorCode.INVALID_INPUT */ 19685 , `${imgDirectiveDetails(dir.ngSrc)} the aspect ratio of the rendered image ` + `does not match the image's intrinsic aspect ratio. ` + `\nIntrinsic image size: ${intrinsicWidth}w x ${intrinsicHeight}h ` + `(aspect-ratio: ${intrinsicAspectRatio}). \nRendered image size: ` + `${renderedWidth}w x ${renderedHeight}h (aspect-ratio: ` + `${renderedAspectRatio}). \nThis issue can occur if "width" and "height" ` + `attributes are added to an image without updating the corresponding ` + `image styling. To fix this, adju
19685st image styling. In most cases, ` + `adding "height: auto" or "width: auto" to the image styling will fix ` + `this issue.`)); 19686 } else if (!dir.ngSrcset && nonZeroRenderedDimensions) { 19687 // If `ngSrcset` hasn't been set, sanity check the intrinsic size. 19688 const recommendedWidth = RECOMMENDED_SRCSET_DENSITY_CAP * renderedWidth; 19689 const recommendedHeight = RECOMMENDED_SRCSET_DENSITY_CAP * renderedHeight; 19690 const oversizedWidth = intrinsicWidth - recommendedWidth >= OVERSIZED_IMAGE_TOLERANCE; 19691 const oversizedHeight = intrinsicHeight - recommendedHeight >= OVERSIZED_IMAGE_TOLERANCE; 19692 19693 if (oversizedWidth || oversizedHeight) { 19694 console.warn((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵformatRuntimeError"])(2960 19695 /* RuntimeErrorCode.OVERSIZED_IMAGE */ 19696 , `${imgDirectiveDetails(dir.ngSrc)} the intrinsic image is significantly ` + `larger than necessary. ` + `\nRendered image size: ${renderedWidth}w x ${renderedHeight}h. ` + `\nIntrinsic image size: ${intrinsicWidth}w x ${intrinsicHeight}h. ` + `\nRecommended intrinsic image size: ${recommendedWidth}w x ${recommendedHeight}h. ` + `\nNote: Recommended intrinsic image size is calculated assuming a maximum DPR of ` + `${RECOMMENDED_SRCSET_DENSITY_CAP}. To improve loading time, resize the image ` + `or consider using the "ngSrcset" and "sizes" attributes.`)); 19697 } 19698 } 19699 }); 19700} 19701/** 19702 * Verifies that a specified input is set. 19703 */ 19704 19705 19706function assertNonEmptyWidthAndHeight(dir) { 19707 let missingAttributes = []; 19708 if (dir.width === undefined) missingAttributes.push('width'); 19709 if (dir.height === undefined) missingAttributes.push('height'); 19710 19711 if (missingAttributes.length > 0) { 19712 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2954 19713 /* RuntimeErrorCode.REQUIRED_INPUT_MISSING */ 19714 , `${imgDirectiveDetails(dir.ngSrc)} these required attributes ` + `are missing: ${missingAttributes.map(attr => `"${attr}"`).join(', ')}. ` + `Including "width" and "height" attributes will prevent image-related layout shifts. ` + `To fix this, include "width" and "height" attributes on the image tag.`); 19715 } 19716} 19717/** 19718 * Verifies that the `loading` attribute is set to a valid input & 19719 * is not used on priority images. 19720 */ 19721 19722 19723function assertValidLoadingInput(dir) { 19724 if (dir.loading && dir.priority) { 19725 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952 19726 /* RuntimeErrorCode.INVALID_INPUT */ 19727 , `${imgDirectiveDetails(dir.ngSrc)} the \`loading\` attribute ` + `was used on an image that was marked "priority". ` + `Setting \`loading\` on priority images is not allowed ` + `because these images will always be eagerly loaded. ` + `To fix this, remove the âloadingâ attribute from the priority image.`); 19728 } 19729 19730 const validInputs = ['auto', 'eager', 'lazy']; 19731 19732 if (typeof dir.loading === 'string' && !validInputs.includes(dir.loading)) { 19733 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](2952 19734 /* RuntimeErrorCode.INVALID_INPUT */ 19735 , `${imgDirectiveDetails(dir.ngSrc)} the \`loading\` attribute ` + `has an invalid value (\`${dir.loading}\`). ` + `To fix this, provide a valid value ("lazy", "eager", or "auto").`); 19736 } 19737} 19738/** 19739 * @license 19740 * Copyright Google LLC All Rights Reserved. 19741 * 19742 * Use of this source code is governed by an MIT-style license that can be 19743 * found in the LICENSE file at https://angular.io/license 19744 */ 19745 19746/** 19747 * @license 19748 * Copyright Google LLC All Rights Reserved. 19749 * 19750 * Use of this source code is governed by an MIT-style license that can be 19751 * found in the LICENSE file at https://angular.io/license 19752 */ 19753 19754/** 19755 * @license 19756 * Copyright Google LLC All Rights Reserved. 19757 * 19758 * Use of this source code is governed by an MIT-style license that can be 19759 * found in the LICENSE file at https://angular.io/license 19760 */ 19761// This file only reexports content of the `src` folder. Keep it that way. 19762 19763/** 19764 * @license 19765 * Copyright Google LLC All Rights Reserved. 19766 * 19767 * Use of this source code is governed by an MIT-style license that can be 19768 * found in the LICENSE file at https://angular.io/license 19769 */ 19770 19771/** 19772 * Generated bundle index. Do not edit. 19773 */ 19774 19775 19776 19777 19778/***/ }), 19779 19780/***/ 8987: 19781/*!********************************************************!*\ 19782 !*** ./node_modules/@angular/common/fesm2020/http.mjs ***! 19783 \********************************************************/ 19784/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 19785 19786__webpack_require__.r(__webpack_exports__); 19787/* harmony export */ __webpack_require__.d(__webpack_exports__, { 19788/* harmony export */ "HTTP_INTERCEPTORS": () => (/* binding */ HTTP_INTERCEPTORS), 19789/* harmony export */ "HttpBackend": () => (/* binding */ HttpBackend), 19790/* harmony export */ "HttpClient": () => (/* binding */ HttpClient), 19791/* harmony export */ "HttpClientJsonpModule": () => (/* binding */ HttpClientJsonpModule), 19792/* harmony export */ "HttpClientModule": () => (/* binding */ HttpClientModule), 19793/* harmony export */ "HttpClientXsrfModule": () => (/* binding */ HttpClientXsrfModule), 19794/* harmony export */ "HttpContext": () => (/* binding */ HttpContext), 19795/* harmony export */ "HttpContextToken": () => (/* binding */ HttpContextToken), 19796/* harmony export */ "HttpErrorResponse": () => (/* binding */ HttpErrorResponse), 19797/* harmony export */ "HttpEventType": () => (/* binding */ HttpEventType), 19798/* harmony export */ "HttpHandler": () => (/* binding */ HttpHandler), 19799/* harmony export */ "HttpHeaderResponse": () => (/* binding */ HttpHeaderResponse), 19800/* harmony export */ "HttpHeaders": () => (/* binding */ HttpHeaders), 19801/* harmony export */ "HttpParams": () => (/* binding */ HttpParams), 19802/* harmony export */ "HttpRequest": () => (/* binding */ HttpRequest), 19803/* harmony export */ "HttpResponse": () => (/* binding */ HttpResponse), 19804/* harmony export */ "HttpResponseBase": () => (/* binding */ HttpResponseBase), 19805/* harmony export */ "HttpUrlEncodingCodec": () => (/* binding */ HttpUrlEncodingCodec), 19806/* harmony export */ "HttpXhrBackend": () => (/* binding */ HttpXhrBackend), 19807/* harmony export */ "HttpXsrfTokenExtractor": () => (/* binding */ HttpXsrfTokenExtractor), 19808/* harmony export */ "JsonpClientBackend": () => (/* binding */ JsonpClientBackend), 19809/* harmony export */ "JsonpInterceptor": () => (/* binding */ JsonpInterceptor), 19810/* harmony export */ "XhrFactory": () => (/* binding */ XhrFactory), 19811/* harmony export */ "ɵHttpInterceptingHandler": () => (/* binding */ HttpInterceptingHandler) 19812/* harmony export */ }); 19813/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/common */ 4666); 19814/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 2560); 19815/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! rxjs */ 4139); 19816/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 2378); 19817/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs/operators */ 1133); 19818/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs/operators */ 9151); 19819/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs/operators */ 6942); 19820/** 19821 * @license Angular v14.2.10 19822 * (c) 2010-2022 Google LLC. https://angular.io/ 19823 * License: MIT 19824 */ 19825 19826 19827 19828 19829 19830 19831/** 19832 * @license 19833 * Copyright Google LLC All Rights Reserved. 19834 * 19835 * Use of this source code is governed by an MIT-style license that can be 19836 * found in the LICENSE file at https://angular.io/license 19837 */ 19838 19839/** 19840 * Transforms an `HttpRequest` into a stream of `HttpEvent`s, one of which will likely be a 19841 * `HttpResponse`. 19842 * 19843 * `HttpHandler` is injectable. When injected, the handler instance dispatches requests to the 19844 * first interceptor in the chain, which dispatches to the second, etc, eventually reaching the 19845 * `HttpBackend`. 19846 * 19847 * In an `HttpInterceptor`, the `HttpHandler` parameter is the next interceptor in the chain.
vendor: 16,594 bytes, lines 19848-20515
19848 * 19849 * @publicApi 19850 */ 19851 19852class HttpHandler {} 19853/** 19854 * A final `HttpHandler` which will dispatch the request via browser HTTP APIs to a backend. 19855 * 19856 * Interceptors sit between the `HttpClient` interface and the `HttpBackend`. 19857 * 19858 * When injected, `HttpBackend` dispatches requests directly to the backend, without going 19859 * through the interceptor chain. 19860 * 19861 * @publicApi 19862 */ 19863 19864 19865class HttpBackend {} 19866/** 19867 * @license 19868 * Copyright Google LLC All Rights Reserved. 19869 * 19870 * Use of this source code is governed by an MIT-style license that can be 19871 * found in the LICENSE file at https://angular.io/license 19872 */ 19873 19874/** 19875 * Represents the header configuration options for an HTTP request. 19876 * Instances are immutable. Modifying methods return a cloned 19877 * instance with the change. The original object is never changed. 19878 * 19879 * @publicApi 19880 */ 19881 19882 19883class HttpHeaders { 19884 /** Constructs a new HTTP header object with the given values.*/ 19885 constructor(headers) { 19886 /** 19887 * Internal map of lowercased header names to the normalized 19888 * form of the name (the form seen first). 19889 */ 19890 this.normalizedNames = new Map(); 19891 /** 19892 * Queued updates to be materialized the next initialization. 19893 */ 19894 19895 this.lazyUpdate = null; 19896 19897 if (!headers) { 19898 this.headers = new Map(); 19899 } else if (typeof headers === 'string') { 19900 this.lazyInit = () => { 19901 this.headers = new Map(); 19902 headers.split('\n').forEach(line => { 19903 const index = line.indexOf(':'); 19904 19905 if (index > 0) { 19906 const name = line.slice(0, index); 19907 const key = name.toLowerCase(); 19908 const value = line.slice(index + 1).trim(); 19909 this.maybeSetNormalizedName(name, key); 19910 19911 if (this.headers.has(key)) { 19912 this.headers.get(key).push(value); 19913 } else { 19914 this.headers.set(key, [value]); 19915 } 19916 } 19917 }); 19918 }; 19919 } else { 19920 this.lazyInit = () => { 19921 if (typeof ngDevMode === 'undefined' || ngDevMode) { 19922 assertValidHeaders(headers); 19923 } 19924 19925 this.headers = new Map(); 19926 Object.keys(headers).forEach(name => { 19927 let values = headers[name]; 19928 const key = name.toLowerCase(); 19929 19930 if (typeof values === 'string') { 19931 values = [values]; 19932 } 19933 19934 if (values.length > 0) { 19935 this.headers.set(key, values); 19936 this.maybeSetNormalizedName(name, key); 19937 } 19938 }); 19939 }; 19940 } 19941 } 19942 /** 19943 * Checks for existence of a given header. 19944 * 19945 * @param name The header name to check for existence. 19946 * 19947 * @returns True if the header exists, false otherwise. 19948 */ 19949 19950 19951 has(name) { 19952 this.init(); 19953 return this.headers.has(name.toLowerCase()); 19954 } 19955 /** 19956 * Retrieves the first value of a given header. 19957 * 19958 * @param name The header name. 19959 * 19960 * @returns The value string if the header exists, null otherwise 19961 */ 19962 19963 19964 get(name) { 19965 this.init(); 19966 const values = this.headers.get(name.toLowerCase()); 19967 return values && values.length > 0 ? values[0] : null; 19968 } 19969 /** 19970 * Retrieves the names of the headers. 19971 * 19972 * @returns A list of header names. 19973 */ 19974 19975 19976 keys() { 19977 this.init(); 19978 return Array.from(this.normalizedNames.values()); 19979 } 19980 /** 19981 * Retrieves a list of values for a given header. 19982 * 19983 * @param name The header name from which to retrieve values. 19984 * 19985 * @returns A string of values if the header exists, null otherwise. 19986 */ 19987 19988 19989 getAll(name) { 19990 this.init(); 19991 return this.headers.get(name.toLowerCase()) || null; 19992 } 19993 /** 19994 * Appends a new value to the existing set of values for a header 19995 * and returns them in a clone of the original instance. 19996 * 19997 * @param name The header name for which to append the values. 19998 * @param value The value to append. 19999 * 20000 * @returns A clone of the HTTP headers object with the value appended to the given header. 20001 */ 20002 20003 20004 append(name, value) { 20005 return this.clone({ 20006 name, 20007 value, 20008 op: 'a' 20009 }); 20010 } 20011 /** 20012 * Sets or modifies a value for a given header in a clone of the original instance. 20013 * If the header already exists, its value is replaced with the given value 20014 * in the returned object. 20015 * 20016 * @param name The header name. 20017 * @param value The value or values to set or override for the given header. 20018 * 20019 * @returns A clone of the HTTP headers object with the newly set header value. 20020 */ 20021 20022 20023 set(name, value) { 20024 return this.clone({ 20025 name, 20026 value, 20027 op: 's' 20028 }); 20029 } 20030 /** 20031 * Deletes values for a given header in a clone of the original instance. 20032 * 20033 * @param name The header name. 20034 * @param value The value or values to delete for the given header. 20035 * 20036 * @returns A clone of the HTTP headers object with the given value deleted. 20037 */ 20038 20039 20040 delete(name, value) { 20041 return this.clone({ 20042 name, 20043 value, 20044 op: 'd' 20045 }); 20046 } 20047 20048 maybeSetNormalizedName(name, lcName) { 20049 if (!this.normalizedNames.has(lcName)) { 20050 this.normalizedNames.set(lcName, name); 20051 } 20052 } 20053 20054 init() { 20055 if (!!this.lazyInit) { 20056 if (this.lazyInit instanceof HttpHeaders) { 20057 this.copyFrom(this.lazyInit); 20058 } else { 20059 this.lazyInit(); 20060 } 20061 20062 this.lazyInit = null; 20063 20064 if (!!this.lazyUpdate) { 20065 this.lazyUpdate.forEach(update => this.applyUpdate(update)); 20066 this.lazyUpdate = null; 20067 } 20068 } 20069 } 20070 20071 copyFrom(other) { 20072 other.init(); 20073 Array.from(other.headers.keys()).forEach(key => { 20074 this.headers.set(key, other.headers.get(key)); 20075 this.normalizedNames.set(key, other.normalizedNames.get(key)); 20076 }); 20077 } 20078 20079 clone(update) { 20080 const clone = new HttpHeaders(); 20081 clone.lazyInit = !!this.lazyInit && this.lazyInit instanceof HttpHeaders ? this.lazyInit : this; 20082 clone.lazyUpdate = (this.lazyUpdate || []).concat([update]); 20083 return clone; 20084 } 20085 20086 applyUpdate(update) { 20087 const key = update.name.toLowerCase(); 20088 20089 switch (update.op) { 20090 case 'a': 20091 case 's': 20092 let value = update.value; 20093 20094 if (typeof value === 'string') { 20095 value = [value]; 20096 } 20097 20098 if (value.length === 0) { 20099 return; 20100 } 20101 20102 this.maybeSetNormalizedName(update.name, key); 20103 const base = (update.op === 'a' ? this.headers.get(key) : undefined) || []; 20104 base.push(...value); 20105 this.headers.set(key, base); 20106 break; 20107 20108 case 'd': 20109 const toDelete = update.value; 20110 20111 if (!toDelete) { 20112 this.headers.delete(key); 20113 this.normalizedNames.delete(key); 20114 } else { 20115 let existing = this.headers.get(key); 20116 20117 if (!existing) { 20118 return; 20119 } 20120 20121 existing = existing.filter(value => toDelete.indexOf(value) === -1); 20122 20123 if (existing.length === 0) { 20124 this.headers.delete(key); 20125 this.normalizedNames.delete(key); 20126 } else { 20127 this.headers.set(key, existing); 20128 } 20129 } 20130 20131 break; 20132 } 20133 } 20134 /** 20135 * @internal 20136 */ 20137 20138 20139 forEach(fn) { 20140 this.init(); 20141 Array.from(this.normalizedNames.keys()).forEach(key => fn(this.normalizedNames.get(key), this.headers.get(key))); 20142 } 20143 20144} 20145/** 20146 * Verifies that the headers object has the right shape: the values 20147 * must be either strings or arrays. Throws an error if an invalid 20148 * header value is present. 20149 */ 20150 20151 20152function assertValidHeaders(headers) { 20153 for (const [key, value] of Object.entries(headers)) { 20154 if (typeof value !== 'string' && !Array.isArray(value)) { 20155 throw new Error(`Unexpected value of the \`${key}\` header provided. ` + `Expecting either a string or an array, but got: \`${value}\`.`); 20156 } 20157 } 20158} 20159/** 20160 * @license 20161 * Copyright Google LLC All Rights Reserved. 20162 * 20163 * Use of this source code is governed by an MIT-style license that can be 20164 * found in the LICENSE file at https://angular.io/license 20165 */ 20166 20167/** 20168 * Provides encoding and decoding of URL parameter and query-string values. 20169 * 20170 * Serializes and parses URL parameter keys and values to encode and decode them. 20171 * If you pass URL query parameters without encoding, 20172 * the query parameters can be misinterpreted at the receiving end. 20173 * 20174 * 20175 * @publicApi 20176 */ 20177 20178 20179class HttpUrlEncodingCodec { 20180 /** 20181 * Encodes a key name for a URL parameter or query-string. 20182 * @param key The key name. 20183 * @returns The encoded key name. 20184 */ 20185 encodeKey(key) { 20186 return standardEncoding(key); 20187 } 20188 /** 20189 * Encodes the value of a URL parameter or query-string. 20190 * @param value The value. 20191 * @returns The encoded value. 20192 */ 20193 20194 20195 encodeValue(value) { 20196 return standardEncoding(value); 20197 } 20198 /** 20199 * Decodes an encoded URL parameter or query-string key. 20200 * @param key The encoded key name. 20201 * @returns The decoded key name. 20202 */ 20203 20204 20205 decodeKey(key) { 20206 return decodeURIComponent(key); 20207 } 20208 /** 20209 * Decodes an encoded URL parameter or query-string value. 20210 * @param value The encoded value. 20211 * @returns The decoded value. 20212 */ 20213 20214 20215 decodeValue(value) { 20216 return decodeURIComponent(value); 20217 } 20218 20219} 20220 20221function paramParser(rawParams, codec) { 20222 const map = new Map(); 20223 20224 if (rawParams.length > 0) { 20225 // The `window.location.search` can be used while creating an instance of the `HttpParams` class 20226 // (e.g. `new HttpParams({ fromString: window.location.search })`). The `window.location.search` 20227 // may start with the `?` char, so we strip it if it's present. 20228 const params = rawParams.replace(/^\?/, '').split('&'); 20229 params.forEach(param => { 20230 const eqIdx = param.indexOf('='); 20231 const [key, val] = eqIdx == -1 ? [codec.decodeKey(param), ''] : [codec.decodeKey(param.slice(0, eqIdx)), codec.decodeValue(param.slice(eqIdx + 1))]; 20232 const list = map.get(key) || []; 20233 list.push(val); 20234 map.set(key, list); 20235 }); 20236 } 20237 20238 return map; 20239} 20240/** 20241 * Encode input string with standard encodeURIComponent and then un-encode specific characters. 20242 */ 20243 20244 20245const STANDARD_ENCODING_REGEX = /%(\d[a-f0-9])/gi; 20246const STANDARD_ENCODING_REPLACEMENTS = { 20247 '40': '@', 20248 '3A': ':', 20249 '24': '$', 20250 '2C': ',', 20251 '3B': ';', 20252 '3D': '=', 20253 '3F': '?', 20254 '2F': '/' 20255}; 20256 20257function standardEncoding(v) { 20258 return encodeURIComponent(v).replace(STANDARD_ENCODING_REGEX, (s, t) => STANDARD_ENCODING_REPLACEMENTS[t] ?? s); 20259} 20260 20261function valueToString(value) { 20262 return `${value}`; 20263} 20264/** 20265 * An HTTP request/response body that represents serialized parameters, 20266 * per the MIME type `application/x-www-form-urlencoded`. 20267 * 20268 * This class is immutable; all mutation operations return a new instance. 20269 * 20270 * @publicApi 20271 */ 20272 20273 20274class HttpParams { 20275 constructor(options = {}) { 20276 this.updates = null; 20277 this.cloneFrom = null; 20278 this.encoder = options.encoder || new HttpUrlEncodingCodec(); 20279 20280 if (!!options.fromString) { 20281 if (!!options.fromObject) { 20282 throw new Error(`Cannot specify both fromString and fromObject.`); 20283 } 20284 20285 this.map = paramParser(options.fromString, this.encoder); 20286 } else if (!!options.fromObject) { 20287 this.map = new Map(); 20288 Object.keys(options.fromObject).forEach(key => { 20289 const value = options.fromObject[key]; // convert the values to strings 20290 20291 const values = Array.isArray(value) ? value.map(valueToString) : [valueToString(value)]; 20292 this.map.set(key, values); 20293 }); 20294 } else { 20295 this.map = null; 20296 } 20297 } 20298 /** 20299 * Reports whether the body includes one or more values for a given parameter. 20300 * @param param The parameter name. 20301 * @returns True if the parameter has one or more values, 20302 * false if it has no value or is not present. 20303 */ 20304 20305 20306 has(param) { 20307 this.init(); 20308 return this.map.has(param); 20309 } 20310 /** 20311 * Retrieves the first value for a parameter. 20312 * @param param The parameter name. 20313 * @returns The first value of the given parameter, 20314 * or `null` if the parameter is not present. 20315 */ 20316 20317 20318 get(param) { 20319 this.init(); 20320 const res = this.map.get(param); 20321 return !!res ? res[0] : null; 20322 } 20323 /** 20324 * Retrieves all values for a parameter. 20325 * @param param The parameter name. 20326 * @returns All values in a string array, 20327 * or `null` if the parameter not present. 20328 */ 20329 20330 20331 getAll(param) { 20332 this.init(); 20333 return this.map.get(param) || null; 20334 } 20335 /** 20336 * Retrieves all the parameters for this body. 20337 * @returns The parameter names in a string array. 20338 */ 20339 20340 20341 keys() { 20342 this.init(); 20343 return Array.from(this.map.keys()); 20344 } 20345 /** 20346 * Appends a new value to existing values for a parameter. 20347 * @param param The parameter name. 20348 * @param value The new value to add. 20349 * @return A new body with the appended value. 20350 */ 20351 20352 20353 append(param, value) { 20354 return this.clone({ 20355 param, 20356 value, 20357 op: 'a' 20358 }); 20359 } 20360 /** 20361 * Constructs a new body with appended values for the given parameter name. 20362 * @param params parameters and values 20363 * @return A new body with the new value. 20364 */ 20365 20366 20367 appendAll(params) { 20368 const updates = []; 20369 Object.keys(params).forEach(param => { 20370 const value = params[param]; 20371 20372 if (Array.isArray(value)) { 20373 value.forEach(_value => { 20374 updates.push({ 20375 param, 20376 value: _value, 20377 op: 'a' 20378 }); 20379 }); 20380 } else { 20381 updates.push({ 20382 param, 20383 value: value, 20384 op: 'a' 20385 }); 20386 } 20387 }); 20388 return this.clone(updates); 20389 } 20390 /** 20391 * Replaces the value for a parameter. 20392 * @param param The parameter name. 20393 * @param value The new value. 20394 * @return A new body with the new value. 20395 */ 20396 20397 20398 set(param, value) { 20399 return this.clone({ 20400 param, 20401 value, 20402 op: 's' 20403 }); 20404 } 20405 /** 20406 * Removes a given value or all values from a parameter. 20407 * @param param The parameter name. 20408 * @param value The value to remove, if provided. 20409 * @return A new body with the given value removed, or with all values 20410 * removed if no value is specified. 20411 */ 20412 20413 20414 delete(param, value) { 20415 return this.clone({ 20416 param, 20417 value, 20418 op: 'd' 20419 }); 20420 } 20421 /** 20422 * Serializes the body to an encoded string, where key-value pairs (separated by `=`) are 20423 * separated by `&`s. 20424 */ 20425 20426 20427 toString() { 20428 this.init(); 20429 return this.keys().map(key => { 20430 const eKey = this.encoder.encodeKey(key); // `a: ['1']` produces `'a=1'` 20431 // `b: []` produces `''` 20432 // `c: ['1', '2']` produces `'c=1&c=2'` 20433 20434 return this.map.get(key).map(value => eKey + '=' + this.encoder.encodeValue(value)).join('&'); 20435 }) // filter out empty values because `b: []` produces `''` 20436 // which results in `a=1&&c=1&c=2` instead of `a=1&c=1&c=2` if we don't 20437 .filter(param => param !== '').join('&'); 20438 } 20439 20440 clone(update) { 20441 const clone = new HttpParams({ 20442 encoder: this.encoder 20443 }); 20444 clone.cloneFrom = this.cloneFrom || this; 20445 clone.updates = (this.updates || []).concat(update); 20446 return clone; 20447 } 20448 20449 init() { 20450 if (this.map === null) { 20451 this.map = new Map(); 20452 } 20453 20454 if (this.cloneFrom !== null) { 20455 this.cloneFrom.init(); 20456 this.cloneFrom.keys().forEach(key => this.map.set(key, this.cloneFrom.map.get(key))); 20457 this.updates.forEach(update => { 20458 switch (update.op) { 20459 case 'a': 20460 case 's': 20461 const base = (update.op === 'a' ? this.map.get(update.param) : undefined) || []; 20462 base.push(valueToString(update.value)); 20463 this.map.set(update.param, base); 20464 break; 20465 20466 case 'd': 20467 if (update.value !== undefined) { 20468 let base = this.map.get(update.param) || []; 20469 const idx = base.indexOf(valueToString(update.value)); 20470 20471 if (idx !== -1) { 20472 base.splice(idx, 1); 20473 } 20474 20475 if (base.length > 0) { 20476 this.map.set(update.param, base); 20477 } else { 20478 this.map.delete(update.param); 20479 } 20480 } else { 20481 this.map.delete(update.param); 20482 break; 20483 } 20484 20485 } 20486 }); 20487 this.cloneFrom = this.updates = null; 20488 } 20489 } 20490 20491} 20492/** 20493 * @license 20494 * Copyright Google LLC All Rights Reserved. 20495 * 20496 * Use of this source code is governed by an MIT-style license that can be 20497 * found in the LICENSE file at https://angular.io/license 20498 */ 20499 20500/** 20501 * A token used to manipulate and access values stored in `HttpContext`. 20502 * 20503 * @publicApi 20504 */ 20505 20506 20507class HttpContextToken { 20508 constructor(defaultValue) { 20509 this.defaultValue = defaultValue; 20510 } 20511 20512} 20513/** 20514 * Http context stores arbitrary user defined values and ensures type safety without 20515 * actually knowing the types. It is backed by a `Map` and guarantees that keys do n
20515ot clash. 20516 * 20517 * This context is mutable and is shared between cloned requests unless explicitly specified. 20518 * 20519 * @usageNotes 20520 * 20521 * ### Usage Example 20522 * 20523 * ```typescript 20524 * // inside cache.interceptors.ts 20525 * export const IS_CACHE_ENABLED = new HttpContextToken<boolean>(() => false); 20526 * 20527 * export class CacheInterceptor implements HttpInterceptor { 20528 * 20529 * intercept(req: HttpRequest<any>, delegate: HttpHandler): Observable<HttpEvent<any>> { 20530 * if (req.context.get(IS_CACHE_ENABLED) === true) { 20531 * return ...; 20532 * } 20533 * return delegate.handle(req); 20534 * } 20535 * } 20536 * 20537 * // inside a service 20538 * 20539 * this.httpClient.get('/api/weather', { 20540 * context: new HttpContext().set(IS_CACHE_ENABLED, true) 20541 * }).subscribe(...); 20542 * ``` 20543 * 20544 * @publicApi 20545 */ 20546 20547 20548class HttpContext { 20549 constructor() { 20550 this.map = new Map(); 20551 } 20552 /** 20553 * Store a value in the context. If a value is already present it will be overwritten. 20554 * 20555 * @param token The reference to an instance of `HttpContextToken`. 20556 * @param value The value to store. 20557 * 20558 * @returns A reference to itself for easy chaining. 20559 */ 20560 20561 20562 set(token, value) { 20563 this.map.set(token, value); 20564 return this; 20565 } 20566 /** 20567 * Retrieve the value associated with the given token. 20568 * 20569 * @param token The reference to an instance of `HttpContextToken`. 20570 * 20571 * @returns The stored value or default if one is defined. 20572 */ 20573 20574 20575 get(token) { 20576 if (!this.map.has(token)) { 20577 this.map.set(token, token.defaultValue()); 20578 } 20579 20580 return this.map.get(token); 20581 } 20582 /** 20583 * Delete the value associated with the given token. 20584 * 20585 * @param token The reference to an instance of `HttpContextToken`. 20586 * 20587 * @returns A reference to itself for easy chaining. 20588 */ 20589 20590 20591 delete(token) { 20592 this.map.delete(token); 20593 return this; 20594 } 20595 /** 20596 * Checks for existence of a given token. 20597 * 20598 * @param token The reference to an instance of `HttpContextToken`. 20599 * 20600 * @returns True if the token exists, false otherwise. 20601 */ 20602 20603 20604 has(token) { 20605 return this.map.has(token); 20606 } 20607 /** 20608 * @returns a list of tokens currently stored in the context. 20609 */ 20610 20611 20612 keys() { 20613 return this.map.keys(); 20614 } 20615 20616} 20617/** 20618 * @license 20619 * Copyright Google LLC All Rights Reserved. 20620 * 20621 * Use of this source code is governed by an MIT-style license that can be 20622 * found in the LICENSE file at https://angular.io/license 20623 */ 20624 20625/** 20626 * Determine whether the given HTTP method may include a body. 20627 */ 20628 20629 20630function mightHaveBody(method) { 20631 switch (method) { 20632 case 'DELETE': 20633 case 'GET': 20634 case 'HEAD': 20635 case 'OPTIONS': 20636 case 'JSONP': 20637 return false; 20638 20639 default: 20640 return true; 20641 } 20642} 20643/** 20644 * Safely assert whether the given value is an ArrayBuffer. 20645 * 20646 * In some execution environments ArrayBuffer is not defined. 20647 */ 20648 20649 20650function isArrayBuffer(value) { 20651 return typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer; 20652} 20653/** 20654 * Safely assert whether the given value is a Blob. 20655 * 20656 * In some execution environments Blob is not defined. 20657 */ 20658 20659 20660function isBlob(value) { 20661 return typeof Blob !== 'undefined' && value instanceof Blob; 20662} 20663/** 20664 * Safely assert whether the given value is a FormData instance. 20665 * 20666 * In some execution environments FormData is not defined. 20667 */ 20668 20669 20670function isFormData(value) { 20671 return typeof FormData !== 'undefined' && value instanceof FormData; 20672} 20673/** 20674 * Safely assert whether the given value is a URLSearchParams instance. 20675 * 20676 * In some execution environments URLSearchParams is not defined. 20677 */ 20678 20679 20680function isUrlSearchParams(value) { 20681 return typeof URLSearchParams !== 'undefined' && value instanceof URLSearchParams; 20682} 20683/** 20684 * An outgoing HTTP request with an optional typed body. 20685 * 20686 * `HttpRequest` represents an outgoing request, including URL, method, 20687 * headers, body, and other request configuration options. Instances should be 20688 * assumed to be immutable. To modify a `HttpRequest`, the `clone` 20689 * method should be used. 20690 * 20691 * @publicApi 20692 */ 20693 20694 20695class HttpRequest { 20696 constructor(method, url, third, fourth) { 20697 this.url = url; 20698 /** 20699 * The request body, or `null` if one isn't set. 20700 * 20701 * Bodies are not enforced to be immutable, as they can include a reference to any 20702 * user-defined data type. However, interceptors should take care to preserve 20703 * idempotence by treating them as such. 20704 */ 20705 20706 this.body = null; 20707 /** 20708 * Whether this request should be made in a way that exposes progress events. 20709 * 20710 * Progress events are expensive (change detection runs on each event) and so 20711 * they should only be requested if the consumer intends to monitor them. 20712 */ 20713 20714 this.reportProgress = false;
vendor: 11,869 bytes, lines 20715-21089
20715 /** 20716 * Whether this request should be sent with outgoing credentials (cookies). 20717 */ 20718 20719 this.withCredentials = false; 20720 /** 20721 * The expected response type of the server. 20722 * 20723 * This is used to parse the response appropriately before returning it to 20724 * the requestee. 20725 */ 20726 20727 this.responseType = 'json'; 20728 this.method = method.toUpperCase(); // Next, need to figure out which argument holds the HttpRequestInit 20729 // options, if any. 20730 20731 let options; // Check whether a body argument is expected. The only valid way to omit 20732 // the body argument is to use a known no-body method like GET. 20733 20734 if (mightHaveBody(this.method) || !!fourth) { 20735 // Body is the third argument, options are the fourth. 20736 this.body = third !== undefined ? third : null; 20737 options = fourth; 20738 } else { 20739 // No body required, options are the third argument. The body stays null. 20740 options = third; 20741 } // If options have been passed, interpret them. 20742 20743 20744 if (options) { 20745 // Normalize reportProgress and withCredentials. 20746 this.reportProgress = !!options.reportProgress; 20747 this.withCredentials = !!options.withCredentials; // Override default response type of 'json' if one is provided. 20748 20749 if (!!options.responseType) { 20750 this.responseType = options.responseType; 20751 } // Override headers if they're provided. 20752 20753 20754 if (!!options.headers) { 20755 this.headers = options.headers; 20756 } 20757 20758 if (!!options.context) { 20759 this.context = options.context; 20760 } 20761 20762 if (!!options.params) { 20763 this.params = options.params; 20764 } 20765 } // If no headers have been passed in, construct a new HttpHeaders instance. 20766 20767 20768 if (!this.headers) { 20769 this.headers = new HttpHeaders(); 20770 } // If no context have been passed in, construct a new HttpContext instance. 20771 20772 20773 if (!this.context) { 20774 this.context = new HttpContext(); 20775 } // If no parameters have been passed in, construct a new HttpUrlEncodedParams instance. 20776 20777 20778 if (!this.params) { 20779 this.params = new HttpParams(); 20780 this.urlWithParams = url; 20781 } else { 20782 // Encode the parameters to a string in preparation for inclusion in the URL. 20783 const params = this.params.toString(); 20784 20785 if (params.length === 0) { 20786 // No parameters, the visible URL is just the URL given at creation time. 20787 this.urlWithParams = url; 20788 } else { 20789 // Does the URL already have query parameters? Look for '?'. 20790 const qIdx = url.indexOf('?'); // There are 3 cases to handle: 20791 // 1) No existing parameters -> append '?' followed by params. 20792 // 2) '?' exists and is followed by existing query string -> 20793 // append '&' followed by params. 20794 // 3) '?' exists at the end of the url -> append params directly. 20795 // This basically amounts to determining the character, if any, with 20796 // which to join the URL and parameters. 20797 20798 const sep = qIdx === -1 ? '?' : qIdx < url.length - 1 ? '&' : ''; 20799 this.urlWithParams = url + sep + params; 20800 } 20801 } 20802 } 20803 /** 20804 * Transform the free-form body into a serialized format suitable for 20805 * transmission to the server. 20806 */ 20807 20808 20809 serializeBody() { 20810 // If no body is present, no need to serialize it. 20811 if (this.body === null) { 20812 return null; 20813 } // Check whether the body is already in a serialized form. If so, 20814 // it can just be returned directly. 20815 20816 20817 if (isArrayBuffer(this.body) || isBlob(this.body) || isFormData(this.body) || isUrlSearchParams(this.body) || typeof this.body === 'string') { 20818 return this.body; 20819 } // Check whether the body is an instance of HttpUrlEncodedParams. 20820 20821 20822 if (this.body instanceof HttpParams) { 20823 return this.body.toString(); 20824 } // Check whether the body is an object or array, and serialize with JSON if so. 20825 20826 20827 if (typeof this.body === 'object' || typeof this.body === 'boolean' || Array.isArray(this.body)) { 20828 return JSON.stringify(this.body); 20829 } // Fall back on toString() for everything else. 20830 20831 20832 return this.body.toString(); 20833 } 20834 /** 20835 * Examine the body and attempt to infer an appropriate MIME type 20836 * for it. 20837 * 20838 * If no such type can be inferred, this method will return `null`. 20839 */ 20840 20841 20842 detectContentTypeHeader() { 20843 // An empty body has no content type. 20844 if (this.body === null) { 20845 return null; 20846 } // FormData bodies rely on the browser's content type assignment. 20847 20848 20849 if (isFormData(this.body)) { 20850 return null; 20851 } // Blobs usually have their own content type. If it doesn't, then 20852 // no type can be inferred. 20853 20854 20855 if (isBlob(this.body)) { 20856 return this.body.type || null; 20857 } // Array buffers have unknown contents and thus no type can be inferred. 20858 20859 20860 if (isArrayBuffer(this.body)) { 20861 return null; 20862 } // Technically, strings could be a form of JSON data, but it's safe enough 20863 // to assume they're plain strings. 20864 20865 20866 if (typeof this.body === 'string') { 20867 return 'text/plain'; 20868 } // `HttpUrlEncodedParams` has its own content-type. 20869 20870 20871 if (this.body instanceof HttpParams) { 20872 return 'application/x-www-form-urlencoded;charset=UTF-8'; 20873 } // Arrays, objects, boolean and numbers will be encoded as JSON. 20874 20875 20876 if (typeof this.body === 'object' || typeof this.body === 'number' || typeof this.body === 'boolean') { 20877 return 'application/json'; 20878 } // No type could be inferred. 20879 20880 20881 return null; 20882 } 20883 20884 clone(update = {}) { 20885 // For method, url, and responseType, take the current value unless 20886 // it is overridden in the update hash. 20887 const method = update.method || this.method; 20888 const url = update.url || this.url; 20889 const responseType = update.responseType || this.responseType; // The body is somewhat special - a `null` value in update.body means 20890 // whatever current body is present is being overridden with an empty 20891 // body, whereas an `undefined` value in update.body implies no 20892 // override. 20893 20894 const body = update.body !== undefined ? update.body : this.body; // Carefully handle the boolean options to differentiate between 20895 // `false` and `undefined` in the update args. 20896 20897 const withCredentials = update.withCredentials !== undefined ? update.withCredentials : this.withCredentials; 20898 const reportProgress = update.reportProgress !== undefined ? update.reportProgress : this.reportProgress; // Headers and params may be appended to if `setHeaders` or 20899 // `setParams` are used. 20900 20901 let headers = update.headers || this.headers; 20902 let params = update.params || this.params; // Pass on context if needed 20903 20904 const context = update.context ?? this.context; // Check whether the caller has asked to add headers. 20905 20906 if (update.setHeaders !== undefined) { 20907 // Set every requested header. 20908 headers = Object.keys(update.setHeaders).reduce((headers, name) => headers.set(name, update.setHeaders[name]), headers); 20909 } // Check whether the caller has asked to set params. 20910 20911 20912 if (update.setParams) { 20913 // Set every requested param. 20914 params = Object.keys(update.setParams).reduce((params, param) => params.set(param, update.setParams[param]), params); 20915 } // Finally, construct the new HttpRequest using the pieces from above. 20916 20917 20918 return new HttpRequest(method, url, body, { 20919 params, 20920 headers, 20921 context, 20922 reportProgress, 20923 responseType, 20924 withCredentials 20925 }); 20926 } 20927 20928} 20929/** 20930 * @license 20931 * Copyright Google LLC All Rights Reserved. 20932 * 20933 * Use of this source code is governed by an MIT-style license that can be 20934 * found in the LICENSE file at https://angular.io/license 20935 */ 20936 20937/** 20938 * Type enumeration for the different kinds of `HttpEvent`. 20939 * 20940 * @publicApi 20941 */ 20942 20943 20944var HttpEventType; 20945 20946(function (HttpEventType) { 20947 /** 20948 * The request was sent out over the wire. 20949 */ 20950 HttpEventType[HttpEventType["Sent"] = 0] = "Sent"; 20951 /** 20952 * An upload progress event was received. 20953 */ 20954 20955 HttpEventType[HttpEventType["UploadProgress"] = 1] = "UploadProgress"; 20956 /** 20957 * The response status code and headers were received. 20958 */ 20959 20960 HttpEventType[HttpEventType["ResponseHeader"] = 2] = "ResponseHeader"; 20961 /** 20962 * A download progress event was received. 20963 */ 20964 20965 HttpEventType[HttpEventType["DownloadProgress"] = 3] = "DownloadProgress"; 20966 /** 20967 * The full response including the body was received. 20968 */ 20969 20970 HttpEventType[HttpEventType["Response"] = 4] = "Response"; 20971 /** 20972 * A custom event from an interceptor or a backend. 20973 */ 20974 20975 HttpEventType[HttpEventType["User"] = 5] = "User"; 20976})(HttpEventType || (HttpEventType = {})); 20977/** 20978 * Base class for both `HttpResponse` and `HttpHeaderResponse`. 20979 * 20980 * @publicApi 20981 */ 20982 20983 20984class HttpResponseBase { 20985 /** 20986 * Super-constructor for all responses. 20987 * 20988 * The single parameter accepted is an initialization hash. Any properties 20989 * of the response passed there will override the default values. 20990 */ 20991 constructor(init, defaultStatus = 200 20992 /* HttpStatusCode.Ok */ 20993 , defaultStatusText = 'OK') { 20994 // If the hash has values passed, use them to initialize the response. 20995 // Otherwise use the default values. 20996 this.headers = init.headers || new HttpHeaders(); 20997 this.status = init.status !== undefined ? init.status : defaultStatus; 20998 this.statusText = init.statusText || defaultStatusText; 20999 this.url = init.url || null; // Cache the ok value to avoid defining a getter. 21000 21001 this.ok = this.status >= 200 && this.status < 300; 21002 } 21003 21004} 21005/** 21006 * A partial HTTP response which only includes the status and header data, 21007 * but no response body. 21008 * 21009 * `HttpHeaderResponse` is a `HttpEvent` available on the response 21010 * event stream, only when progress events are requested. 21011 * 21012 * @publicApi 21013 */ 21014 21015 21016class HttpHeaderResponse extends HttpResponseBase { 21017 /** 21018 * Create a new `HttpHeaderResponse` with the given parameters. 21019 */ 21020 constructor(init = {}) { 21021 super(init); 21022 this.type = HttpEventType.ResponseHeader; 21023 } 21024 /** 21025 * Copy this `HttpHeaderResponse`, overriding its contents with the 21026 * given parameter hash. 21027 */ 21028 21029 21030 clone(update = {}) { 21031 // Perform a straightforward initialization of the new HttpHeaderResponse, 21032 // overriding the current parameters with new ones if given. 21033 return new HttpHeaderResponse({ 21034 headers: update.headers || this.headers, 21035 status: update.status !== undefined ? update.status : this.status, 21036 statusText: update.statusText || this.statusText, 21037 url: update.url || this.url || undefined 21038 }); 21039 } 21040 21041} 21042/** 21043 * A full HTTP response, including a typed response body (which may be `null` 21044 * if one was not returned). 21045 * 21046 * `HttpResponse` is a `HttpEvent` available on the response event 21047 * stream. 21048 * 21049 * @publicApi 21050 */ 21051 21052 21053class HttpResponse extends HttpResponseBase { 21054 /** 21055 * Construct a new `HttpResponse`. 21056 */ 21057 constructor(init = {}) { 21058 super(init); 21059 this.type = HttpEventType.Response; 21060 this.body = init.body !== undefined ? init.body : null; 21061 } 21062 21063 clone(update = {}) { 21064 return new HttpResponse({ 21065 body: update.body !== undefined ? update.body : this.body, 21066 headers: update.headers || this.headers, 21067 status: update.status !== undefined ? update.status : this.status, 21068 statusText: update.statusText || this.statusText, 21069 url: update.url || this.url || undefined 21070 }); 21071 } 21072 21073} 21074/** 21075 * A response that represents an error or failure, either from a 21076 * non-successful HTTP status, an error while executing the request, 21077 * or some other failure which occurred during the parsing of the response. 21078 * 21079 * Any error returned on the `Observable` response stream will be 21080 * wrapped in an `HttpErrorResponse` to provide additional context about 21081 * the state of the HTTP layer when the error occurred. The error property 21082 * will contain either a wrapped Error object or the error response returned 21083 * from the server. 21084 * 21085 * @publicApi 21086 */ 21087 21088 21089class HttpErrorResponse extends HttpResponseBase {
21090 constructor(init) { 21091 // Initialize with a default status of 0 / Unknown Error. 21092 super(init, 0, 'Unknown Error'); 21093 this.name = 'HttpErrorResponse'; 21094 /** 21095 * Errors are never okay, even when the status code is in the 2xx success range. 21096 */ 21097 21098 this.ok = false; // If the response was successful, then this was a parse error. Otherwise, it was 21099 // a protocol-level failure of some sort. Either the request failed in transit 21100 // or the server returned an unsuccessful status code. 21101 21102 if (this.status >= 200 && this.status < 300) { 21103 this.message = `Http failure during parsing for ${init.url || '(unknown url)'}`; 21104 } else { 21105 this.message = `Http failure response for ${init.url || '(unknown url)'}: ${init.status} ${init.statusText}`; 21106 } 21107 21108 this.error = init.error || null; 21109 } 21110 21111} 21112/** 21113 * @license 21114 * Copyright Google LLC All Rights Reserved. 21115 * 21116 * Use of this source code is governed by an MIT-style license that can be 21117 * found in the LICENSE file at https://angular.io/license 21118 */ 21119 21120/** 21121 * Constructs an instance of `HttpRequestOptions<T>` from a source `HttpMethodOptions` and 21122 * the given `body`. This function clones the object and adds the body. 21123 * 21124 * Note that the `responseType` *options* value is a String that identifies the 21125 * single data type of the response. 21126 * A single overload version of the method handles each response type. 21127 * The value of `responseType` cannot be a union, as the combined signature could imply. 21128 * 21129 */ 21130 21131 21132function addBody(options, body) { 21133 return { 21134 body, 21135 headers: options.headers, 21136 context: options.context, 21137 observe: options.observe, 21138 params: options.params, 21139 reportProgress: options.reportProgress, 21140 responseType: options.responseType, 21141 withCredentials: options.withCredentials 21142 }; 21143} 21144/** 21145 * Performs HTTP requests. 21146 * This service is available as an injectable class, with methods to perform HTTP requests. 21147 * Each request method has multiple signatures, and the return type varies based on 21148 * the signature that is called (mainly the values of `observe` and `responseType`). 21149 * 21150 * Note that the `responseType` *options* value is a String that identifies the 21151 * single data type of the response. 21152 * A single overload version of the method handles each response type. 21153 * The value of `responseType` cannot be a union, as the combined signature could imply. 21154 21155 * 21156 * @usageNotes 21157 * Sample HTTP requests for the [Tour of Heroes](/tutorial/toh-pt0) application. 21158 * 21159 * ### HTTP Request Example 21160 * 21161 * ``` 21162 * // GET heroes whose name contains search term 21163 * searchHeroes(term: string): observable<Hero[]>{ 21164 * 21165 * const params = new HttpParams({fromString: 'name=term'}); 21166 * return this.httpClient.request('GET', this.heroesUrl, {responseType:'json', params}); 21167 * } 21168 * ``` 21169 * 21170 * Alternatively, the parameter string can be used without invoking HttpParams 21171 * by directly joining to the URL. 21172 * ``` 21173 * this.httpClient.request('GET', this.heroesUrl + '?' + 'name=term', {responseType:'json'}); 21174 * ``` 21175 * 21176 * 21177 * ### JSONP Example 21178 * ``` 21179 * requestJsonp(url, callback = 'callback') { 21180 * return this.httpClient.jsonp(this.heroesURL, callback); 21181 * } 21182 * ``` 21183 * 21184 * ### PATCH Example 21185 * ``` 21186 * // PATCH one of the heroes' name 21187 * patchHero (id: number, heroName: string): Observable<{}> { 21188 * const url = `${this.heroesUrl}/${id}`; // PATCH api/heroes/42 21189 * return this.httpClient.patch(url, {name: heroName}, httpOptions) 21190 * .pipe(catchError(this.handleError('patchHero'))); 21191 * } 21192 * ``` 21193 * 21194 * @see [HTTP Guide](guide/http) 21195 * @see [HTTP Request](api/common/http/HttpRequest) 21196 * 21197 * @publicApi 21198 */ 21199 21200 21201class HttpClient { 21202 constructor(handler) { 21203 this.handler = handler; 21204 } 21205 /** 21206 * Constructs an observable for a generic HTTP request that, when subscribed, 21207 * fires the request through the chain of registered interceptors and on to the 21208 * server. 21209 * 21210 * You can pass an `HttpRequest` directly as the only parameter. In this case, 21211 * the call returns an observable of the raw `HttpEvent` stream. 21212 * 21213 * Alternatively you can pass an HTTP method as the first parameter, 21214 * a URL string as the second, and an options hash containing the request body as the third. 21215 * See `addBody()`. In this case, the specified `responseType` and `observe` options determine the 21216 * type of returned observable. 21217 * * The `responseType` value determines how a successful response body is parsed. 21218 * * If `responseType` is the default `json`, you can pass a type interface for the resulting 21219 * object as a type parameter to the call. 21220 * 21221 * The `observe` value determines the return type, according to what you are interested in 21222 * observing. 21223 * * An `observe` value of events returns an observable of the raw `HttpEvent` stream, including 21224 * progress events by default. 21225 * * An `observe` value of response returns an observable of `HttpResponse<T>`, 21226 * where the `T` parameter depends on the `responseType` and any optionally provided type 21227 * parameter. 21228 * * An `observe` value of body returns an observable of `<T>` with the same `T` body type. 21229 * 21230 */ 21231 21232 21233 request(first, url, options = {}) { 21234 let req; // First, check whether the primary argument is an instance of `HttpRequest`. 21235 21236 if (first instanceof HttpRequest) { 21237 // It is. The other arguments must be undefined (per the signatures) and can be 21238 // ignored. 21239 req = first; 21240 } else { 21241 // It's a string, so it represents a URL. Construct a request based on it, 21242 // and incorporate the remaining arguments (assuming `GET` unless a method is 21243 // provided. 21244 // Figure out the headers. 21245 let headers = undefined; 21246 21247 if (options.headers instanceof HttpHeaders) { 21248 headers = options.headers; 21249 } else { 21250 headers = new HttpHeaders(options.headers); 21251 } // Sort out parameters. 21252 21253 21254 let params = undefined; 21255 21256 if (!!options.params) { 21257 if (options.params instanceof HttpParams) { 21258 params = options.params; 21259 } else { 21260 params = new HttpParams({ 21261 fromObject: options.params 21262 }); 21263 } 21264 } // Construct the request. 21265 21266 21267 req = new HttpRequest(first, url, options.body !== undefined ? options.body : null, { 21268 headers, 21269 context: options.context, 21270 params, 21271 reportProgress: options.reportProgress, 21272 // By default, JSON is assumed to be returned for all calls. 21273 responseType: options.responseType || 'json', 21274 withCredentials: options.withCredentials 21275 }); 21276 } // Start with an Observable.of() the initial request, and run the handler (which 21277 // includes all interceptors) inside a concatMap(). This way, the handler runs 21278 // inside an Observable chain, which causes interceptors to be re-run on every
21279 // subscription (this also makes retries re-run the handler, including interceptors). 21280 21281 21282 const events$ = (0,rxjs__WEBPACK_IMPORTED_MODULE_0__.of)(req).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_1__.concatMap)(req => this.handler.handle(req))); // If coming via the API signature which accepts a previously constructed HttpRequest, 21283 // the only option is to get the event stream. Otherwise, return the event stream if 21284 // that is what was requested. 21285 21286 if (first instanceof HttpRequest || options.observe === 'events') { 21287 return events$; 21288 } // The requested stream contains either the full response or the body. In either 21289 // case, the first step is to filter the event stream to extract a stream of 21290 // responses(s). 21291 21292 21293 const res$ = events$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_2__.filter)(event => event instanceof HttpResponse)); // Decide which stream to return. 21294 21295 switch (options.observe || 'body') { 21296 case 'body': 21297 // The requested stream is the body. Map the response stream to the response 21298 // body. This could be done more simply, but a misbehaving interceptor might 21299 // transform the response body into a different format and ignore the requested 21300 // responseType. Guard against this by validating that the response is of the 21301 // requested type. 21302 switch (req.responseType) { 21303 case 'arraybuffer': 21304 return res$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_3__.map)(res => { 21305 // Validate that the body is an ArrayBuffer. 21306 if (res.body !== null && !(res.body instanceof ArrayBuffer)) { 21307 throw new Error('Response is not an ArrayBuffer.'); 21308 } 21309 21310 return res.body; 21311 })); 21312 21313 case 'blob': 21314 return res$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_3__.map)(res => { 21315 // Validate that the body is a Blob. 21316 if (res.body !== null && !(res.body instanceof Blob)) { 21317 throw new Error('Response is not a Blob.'); 21318 } 21319 21320 return res.body; 21321 })); 21322 21323 case 'text': 21324 return res$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_3__.map)(res => { 21325 // Validate that the body is a string. 21326 if (res.body !== null && typeof res.body !== 'string') { 21327 throw new Error('Response is not a string.'); 21328 } 21329 21330 return res.body; 21331 })); 21332 21333 case 'json': 21334 default: 21335 // No validation needed for JSON responses, as they can be of any type. 21336 return res$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_3__.map)(res => res.body)); 21337 } 21338 21339 case 'response': 21340 // The response stream was requested directly, so return it. 21341 return res$; 21342 21343 default: 21344 // Guard against new future observe types being added. 21345 throw new Error(`Unreachable: unhandled observe type ${options.observe}}`); 21346 } 21347 } 21348 /** 21349 * Constructs an observable that, when subscribed, causes the configured 21350 * `DELETE` request to execute on the server. See the individual overloads for 21351 * details on the return type. 21352 * 21353 * @param url The endpoint URL. 21354 * @param options The HTTP options to send with the request. 21355 * 21356 */ 21357 21358 21359 delete(url, options = {}) { 21360 return this.request('DELETE', url, options); 21361 } 21362 /** 21363 * Constructs an observable that, when subscribed, causes the configured 21364 * `GET` request to execute on the server. See the individual overloads for 21365 * details on the return type. 21366 */ 21367 21368 21369 get(url, options = {}) { 21370 return this.request('GET', url, options); 21371 } 21372 /** 21373 * Constructs an observable that, when subscribed, causes the configured 21374 * `HEAD` request to execute on the server. The `HEAD` method returns 21375 * meta information about the resource without transferring the 21376 * resource itself. See the individual overloads for 21377 * details on the return type. 21378 */ 21379 21380 21381 head(url, options = {}) { 21382 return this.request('HEAD', url, options); 21383 } 21384 /** 21385 * Constructs an `Observable` that, when subscribed, causes a request with the special method 21386 * `JSONP` to be dispatched via the interceptor pipeline. 21387 * The [JSONP pattern](https://en.wikipedia.org/wiki/JSONP) works around limitations of certain 21388 * API endpoints that don't support newer, 21389 * and preferable [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) protocol. 21390 * JSONP treats the endpoint API as a JavaScript file and tricks the browser to process the 21391 * requests even if the API endpoint is not located on the same domain (origin) as the client-side 21392 * application making the request. 21393 * The endpoint API must support JSONP callback for JSONP requests to work. 21394 * The resource API returns the JSON response wrapped in a callback function. 21395 * You can pass the callback function name as one of the query parameters. 21396 * Note that JSONP requests can only be used with `GET` requests. 21397 * 21398 * @param url The resource URL. 21399 * @param callbackParam The callback function name. 21400 * 21401 */ 21402 21403 21404 jsonp(url, callbackParam) { 21405 return this.request('JSONP', url, { 21406 params: new HttpParams().append(callbackParam, 'JSONP_CALLBACK'), 21407 observe: 'body', 21408 responseType: 'json' 21409 }); 21410 } 21411 /** 21412 * Constructs an `Observable` that, when subscribed, causes the configured 21413 * `OPTIONS` request to execute on the server. This method allows the client 21414 * to determine the supported HTTP methods and other capabilities of an endpoint, 21415 * without implying a resource action. See the individual overloads for 21416 * details on the return type. 21417 */ 21418 21419 21420 options(url, options = {}) { 21421 return this.request('OPTIONS', url, options); 21422 } 21423 /** 21424 * Constructs an observable that, when subscribed, causes the configured 21425 * `PATCH` request to execute on the server. See the individual overloads for 21426 * details on the return type. 21427 */ 21428 21429 21430 patch(url, body, options = {}) { 21431 return this.request('PATCH', url, addBody(options, body)); 21432 } 21433 /** 21434 * Constructs an observable that, when subscribed, causes the configured 21435 * `POST` request to execute on the server. The server responds with the location of 21436 * the replaced resource. See the individual overloads for 21437 * details on the return type. 21438 */ 21439 21440 21441 post(url, body, options = {}) { 21442 return this.request('POST', url, addBody(options, body)); 21443 } 21444 /** 21445 * Constructs an observable that, when subscribed, causes the configured 21446 * `PUT` request to execute on the server. The `PUT` method replaces an existing resource 21447 * with a new set of values. 21448 * See the individual overloads for details on the return type. 21449 */ 21450 21451 21452 put(url, body, options = {}) { 21453 return this.request('PUT', url, addBody(options, body)); 21454 } 21455 21456} 21457
21458HttpClient.ɵfac = function HttpClient_Factory(t) { 21459 return new (t || HttpClient)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](HttpHandler)); 21460}; 21461 21462HttpClient.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({ 21463 token: HttpClient, 21464 factory: HttpClient.ɵfac 21465}); 21466 21467(function () { 21468 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpClient, [{ 21469 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable 21470 }], function () { 21471 return [{ 21472 type: HttpHandler 21473 }]; 21474 }, null); 21475})(); 21476/** 21477 * @license 21478 * Copyright Google LLC All Rights Reserved. 21479 * 21480 * Use of this source code is governed by an MIT-style license that can be 21481 * found in the LICENSE file at https://angular.io/license 21482 */ 21483 21484/** 21485 * `HttpHandler` which applies an `HttpInterceptor` to an `HttpRequest`. 21486 * 21487 * 21488 */ 21489 21490 21491class HttpInterceptorHandler { 21492 constructor(next, interceptor) { 21493 this.next = next; 21494 this.interceptor = interceptor; 21495 } 21496 21497 handle(req) { 21498 return this.interceptor.intercept(req, this.next); 21499 } 21500 21501} 21502/** 21503 * A multi-provider token that represents the array of registered 21504 * `HttpInterceptor` objects. 21505 * 21506 * @publicApi 21507 */ 21508 21509 21510const HTTP_INTERCEPTORS = new _angular_core__WEBPACK_IMPORTED_MODULE_4__.InjectionToken('HTTP_INTERCEPTORS'); 21511 21512class NoopInterceptor { 21513 intercept(req, next) { 21514 return next.handle(req); 21515 } 21516 21517} 21518 21519NoopInterceptor.ɵfac = function NoopInterceptor_Factory(t) { 21520 return new (t || NoopInterceptor)(); 21521}; 21522 21523NoopInterceptor.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({ 21524 token: NoopInterceptor, 21525 factory: NoopInterceptor.ɵfac 21526}); 21527 21528(function () { 21529 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](NoopInterceptor, [{ 21530 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable 21531 }], null, null); 21532})(); 21533/** 21534 * @license 21535 * Copyright Google LLC All Rights Reserved. 21536 * 21537 * Use of this source code is governed by an MIT-style license that can be 21538 * found in the LICENSE file at https://angular.io/license 21539 */ 21540// Every request made through JSONP needs a callback name that's unique across the 21541// whole page. Each request is assigned an id and the callback name is constructed 21542// from that. The next id to be assigned is tracked in a global variable here that 21543// is shared among all applications on the page. 21544 21545 21546let nextRequestId = 0; 21547/** 21548 * When a pending <script> is unsubscribed we'll move it to this document, so it won't be 21549 * executed. 21550 */ 21551 21552let foreignDocument; // Error text given when a JSONP script is injected, but doesn't invoke the callback 21553// passed in its URL. 21554 21555const JSONP_ERR_NO_CALLBACK = 'JSONP injected script did not invoke callback.'; // Error text given when a request is passed to the JsonpClientBackend that doesn't 21556// have a request method JSONP. 21557 21558const JSONP_ERR_WRONG_METHOD = 'JSONP requests must use JSONP request method.'; 21559const JSONP_ERR_WRONG_RESPONSE_TYPE = 'JSONP requests must use Json response type.'; // Error text given when a request is passed to the JsonpClientBackend that has 21560// headers set 21561 21562const JSONP_ERR_HEADERS_NOT_SUPPORTED = 'JSONP requests do not support headers.'; 21563/** 21564 * DI token/abstract type representing a map of JSONP callbacks. 21565 * 21566 * In the browser, this should always be the `window` object. 21567 * 21568 * 21569 */ 21570 21571class JsonpCallbackContext {} 21572/** 21573 * Processes an `HttpRequest` with the JSONP method, 21574 * by performing JSONP style requests. 21575 * @see `HttpHandler` 21576 * @see `HttpXhrBackend` 21577 * 21578 * @publicApi 21579 */ 21580 21581 21582class JsonpClientBackend { 21583 constructor(callbackMap, document) { 21584 this.callbackMap = callbackMap; 21585 this.document = document; 21586 /** 21587 * A resolved promise that can be used to schedule microtasks in the event handlers. 21588 */ 21589 21590 this.resolvedPromise = Promise.resolve(); 21591 } 21592 /** 21593 * Get the name of the next callback method, by incrementing the global `nextRequestId`. 21594 */ 21595 21596 21597 nextCallback() { 21598 return `ng_jsonp_callback_${nextRequestId++}`; 21599 } 21600 /** 21601 * Processes a JSONP request and returns an event stream of the results. 21602 * @param req The request object. 21603 * @returns An observable of the response events. 21604 * 21605 */ 21606 21607 21608 handle(req) { 21609 // Firstly, check both the method and response type. If either doesn't match 21610 // then the request was improperly routed here and cannot be handled. 21611 if (req.method !== 'JSONP') { 21612 throw new Error(JSONP_ERR_WRONG_METHOD); 21613 } else if (req.responseType !== 'json') { 21614 throw new Error(JSONP_ERR_WRONG_RESPONSE_TYPE); 21615 } // Check the request headers. JSONP doesn't support headers and 21616 // cannot set any that were supplied.
21617 21618 21619 if (req.headers.keys().length > 0) { 21620 throw new Error(JSONP_ERR_HEADERS_NOT_SUPPORTED); 21621 } // Everything else happens inside the Observable boundary. 21622 21623 21624 return new rxjs__WEBPACK_IMPORTED_MODULE_5__.Observable(observer => { 21625 // The first step to make a request is to generate the callback name, and replace the 21626 // callback placeholder in the URL with the name. Care has to be taken here to ensure 21627 // a trailing &, if matched, gets inserted back into the URL in the correct place. 21628 const callback = this.nextCallback(); 21629 const url = req.urlWithParams.replace(/=JSONP_CALLBACK(&|$)/, `=${callback}$1`); // Construct the <script> tag and point it at the URL. 21630 21631 const node = this.document.createElement('script'); 21632 node.src = url; // A JSONP request requires waiting for multiple callbacks. These variables 21633 // are closed over and track state across those callbacks. 21634 // The response object, if one has been received, or null otherwise. 21635 21636 let body = null; // Whether the response callback has been called. 21637 21638 let finished = false; // Set the response callback in this.callbackMap (which will be the window 21639 // object in the browser. The script being loaded via the <script> tag will 21640 // eventually call this callback. 21641 21642 this.callbackMap[callback] = data => { 21643 // Data has been received from the JSONP script. Firstly, delete this callback. 21644 delete this.callbackMap[callback]; // Set state to indicate data was received. 21645 21646 body = data; 21647 finished = true; 21648 }; // cleanup() is a utility closure that removes the <script> from the page and 21649 // the response callback from the window. This logic is used in both the 21650 // success, error, and cancellation paths, so it's extracted out for convenience. 21651 21652 21653 const cleanup = () => { 21654 // Remove the <script> tag if it's still on the page. 21655 if (node.parentNode) { 21656 node.parentNode.removeChild(node); 21657 } // Remove the response callback from the callbackMap (window object in the 21658 // browser). 21659 21660 21661 delete this.callbackMap[callback]; 21662 }; // onLoad() is the success callback which runs after the response callback 21663 // if the JSONP script loads successfully. The event itself is unimportant. 21664 // If something went wrong, onLoad() may run without the response callback 21665 // having been invoked. 21666 21667 21668 const onLoad = event => { 21669 // We wrap it in an extra Promise, to ensure the microtask 21670 // is scheduled after the loaded endpoint has executed any potential microtask itself, 21671 // which is not guaranteed in Internet Explorer and EdgeHTML. See issue #39496 21672 this.resolvedPromise.then(() => { 21673 // Cleanup the page. 21674 cleanup(); // Check whether the response callback has run. 21675 21676 if (!finished) { 21677 // It hasn't, something went wrong with the request. Return an error via 21678 // the Observable error path. All JSONP errors have status 0. 21679 observer.error(new HttpErrorResponse({ 21680 url, 21681 status: 0, 21682 statusText: 'JSONP Error', 21683 error: new Error(JSONP_ERR_NO_CALLBACK) 21684 })); 21685 return; 21686 } // Success. body either contains the response body or null if none was 21687 // returned. 21688 21689 21690 observer.next(new HttpResponse({ 21691 body, 21692 status: 200 21693 /* HttpStatusCode.Ok */ 21694 , 21695 statusText: 'OK', 21696 url 21697 })); // Complete the stream, the response is over. 21698 21699 observer.complete(); 21700 }); 21701 }; // onError() is the error callback, which runs if the script returned generates 21702 // a Javascript error. It emits the error via the Observable error channel as 21703 // a HttpErrorResponse. 21704 21705 21706 const onError = error => { 21707 cleanup(); // Wrap the error in a HttpErrorResponse. 21708 21709 observer.error(new HttpErrorResponse({ 21710 error, 21711 status: 0, 21712 statusText: 'JSONP Error', 21713 url 21714 })); 21715 }; // Subscribe to both the success (load) and error events on the <script> tag, 21716 // and add it to the page. 21717 21718 21719 node.addEventListener('load', onLoad); 21720 node.addEventListener('error', onError); 21721 this.document.body.appendChild(node); // The request has now been successfully sent. 21722 21723 observer.next({ 21724 type: HttpEventType.Sent 21725 }); // Cancellation handler. 21726 21727 return () => { 21728 if (!finished) { 21729 this.removeListeners(node); 21730 } // And finally, clean up the page. 21731 21732 21733 cleanup(); 21734 }; 21735 }); 21736 } 21737 21738 removeListeners(script) { 21739 // Issue #34818 21740 // Changing <script>'s ownerDocument will prevent it from execution. 21741 // https://html.spec.whatwg.org/multipage/scripting.html#execute-the-script-block 21742 if (!foreignDocument) { 21743 foreignDocument = this.document.implementation.createHTMLDocument(); 21744 } 21745 21746 foreignDocument.adoptNode(script); 21747 } 21748 21749} 21750 21751JsonpClientBackend.ɵfac = function JsonpClientBackend_Factory(t) { 21752 return new (t || JsonpClientBackend)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](JsonpCallbackContext), _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_6__.DOCUMENT)); 21753}; 21754 21755JsonpClientBackend.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({ 21756 token: JsonpClientBackend, 21757 factory: JsonpClientBackend.ɵfac 21758}); 21759 21760(function () { 21761 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](JsonpClientBackend, [{ 21762 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable 21763 }], function () { 21764 return [{ 21765 type: JsonpCallbackContext 21766 }, {
21767 type: undefined, 21768 decorators: [{ 21769 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Inject, 21770 args: [_angular_common__WEBPACK_IMPORTED_MODULE_6__.DOCUMENT] 21771 }] 21772 }]; 21773 }, null); 21774})(); 21775/** 21776 * Identifies requests with the method JSONP and 21777 * shifts them to the `JsonpClientBackend`. 21778 * 21779 * @see `HttpInterceptor` 21780 * 21781 * @publicApi 21782 */ 21783 21784 21785class JsonpInterceptor { 21786 constructor(jsonp) { 21787 this.jsonp = jsonp; 21788 } 21789 /** 21790 * Identifies and handles a given JSONP request. 21791 * @param req The outgoing request object to handle. 21792 * @param next The next interceptor in the chain, or the backend 21793 * if no interceptors remain in the chain. 21794 * @returns An observable of the event stream. 21795 */ 21796 21797 21798 intercept(req, next) { 21799 if (req.method === 'JSONP') { 21800 return this.jsonp.handle(req); 21801 } // Fall through for normal HTTP requests. 21802 21803 21804 return next.handle(req); 21805 } 21806 21807} 21808 21809JsonpInterceptor.ɵfac = function JsonpInterceptor_Factory(t) { 21810 return new (t || JsonpInterceptor)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](JsonpClientBackend)); 21811}; 21812 21813JsonpInterceptor.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({ 21814 token: JsonpInterceptor, 21815 factory: JsonpInterceptor.ɵfac 21816}); 21817 21818(function () { 21819 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](JsonpInterceptor, [{ 21820 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable 21821 }], function () { 21822 return [{ 21823 type: JsonpClientBackend 21824 }]; 21825 }, null); 21826})(); 21827/** 21828 * @license 21829 * Copyright Google LLC All Rights Reserved. 21830 * 21831 * Use of this source code is governed by an MIT-style license that can be 21832 * found in the LICENSE file at https://angular.io/license 21833 */ 21834 21835 21836const XSSI_PREFIX = /^\)\]\}',?\n/; 21837/** 21838 * Determine an appropriate URL for the response, by checking either 21839 * XMLHttpRequest.responseURL or the X-Request-URL header. 21840 */ 21841 21842function getResponseUrl(xhr) { 21843 if ('responseURL' in xhr && xhr.responseURL) { 21844 return xhr.responseURL; 21845 } 21846 21847 if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) { 21848 return xhr.getResponseHeader('X-Request-URL'); 21849 } 21850 21851 return null; 21852} 21853/** 21854 * Uses `XMLHttpRequest` to send requests to a backend server. 21855 * @see `HttpHandler` 21856 * @see `JsonpClientBackend` 21857 * 21858 * @publicApi 21859 */ 21860 21861 21862class HttpXhrBackend { 21863 constructor(xhrFactory) { 21864 this.xhrFactory = xhrFactory; 21865 } 21866 /** 21867 * Processes a request and returns a stream of response events. 21868 * @param req The request object. 21869 * @returns An observable of the response events. 21870 */ 21871 21872 21873 handle(req) { 21874 // Quick check to give a better error message when a user attempts to use 21875 // HttpClient.jsonp() without installing the HttpClientJsonpModule 21876 if (req.method === 'JSONP') { 21877 throw new Error(`Attempted to construct Jsonp request without HttpClientJsonpModule installed.`); 21878 } // Everything happens on Observable subscription. 21879 21880 21881 return new rxjs__WEBPACK_IMPORTED_MODULE_5__.Observable(observer => { 21882 // Start by setting up the XHR object with request method, URL, and withCredentials flag. 21883 const xhr = this.xhrFactory.build(); 21884 xhr.open(req.method, req.urlWithParams); 21885 21886 if (!!req.withCredentials) { 21887 xhr.withCredentials = true; 21888 } // Add all the requested headers. 21889 21890 21891 req.headers.forEach((name, values) => xhr.setRequestHeader(name, values.join(','))); // Add an Accept header if one isn't present already. 21892 21893 if (!req.headers.has('Accept')) { 21894 xhr.setRequestHeader('Accept', 'application/json, text/plain, */*'); 21895 } // Auto-detect the Content-Type header if one isn't present already. 21896 21897 21898 if (!req.headers.has('Content-Type')) { 21899 const detectedType = req.detectContentTypeHeader(); // Sometimes Content-Type detection fails. 21900 21901 if (detectedType !== null) { 21902 xhr.setRequestHeader('Content-Type', detectedType); 21903 } 21904 } // Set the responseType if one was requested. 21905 21906 21907 if (req.responseType) { 21908 const responseType = req.responseType.toLowerCase(); // JSON responses need to be processed as text. This is because if the server 21909 // returns an XSSI-prefixed JSON response, the browser will fail to parse it, 21910 // xhr.response will be null, and xhr.responseText cannot be accessed to 21911 // retrieve the prefixed JSON data in order to strip the prefix. Thus, all JSON 21912 // is parsed by first requesting text and then applying JSON.parse. 21913 21914 xhr.responseType = responseType !== 'json' ? responseType : 'text'; 21915 } // Serialize the request body if one is present. If not, this will be set to null. 21916 21917 21918 const reqBody = req.serializeBody(); // If progress events are enabled, response headers will be delivered 21919 // in two events - the HttpHeaderResponse event and the full HttpResponse 21920 // event. However, since response headers don't change in between these 21921 // two events, it doesn't make sense to parse them twice. So headerResponse 21922 // caches the data extracted from the response whenever it's first parsed, 21923 // to ensure parsing isn't duplicated. 21924 21925 let headerResponse = null; // partialFromXhr extracts the HttpHeaderResponse from the current XMLHttpRequest 21926 // state, and memoizes it into headerResponse. 21927 21928 const partialFromXhr = () => { 21929 if (headerResponse !== null) { 21930 return headerResponse; 21931 } 21932 21933 const statusText = xhr.statusText || 'OK'; // Parse headers from XMLHttpRequest - this step is lazy. 21934 21935 const headers = new HttpHeaders(xhr.getAllResponseHeaders()); // Read the response URL from the XMLHttpResponse instance and fall back on the 21936 // request URL. 21937 21938 const url = getResponseUrl(xhr) || req.url; // Construct the HttpHeaderResponse and memoize it. 21939 21940 headerResponse = new HttpHeaderResponse({ 21941 headers, 21942 status: xhr.status, 21943 statusText, 21944 url 21945 }); 21946 return headerResponse; 21947 }; // Next, a few closures are defined for the various events which XMLHttpRequest can 21948 // emit. This allows them to be unregistered as event listeners later. 21949 // First up is the load event, which represents a response being fully available. 21950 21951 21952 const onLoad = () => { 21953 // Read response state from the memoized partial data. 21954 let { 21955 headers, 21956 status, 21957 statusText, 21958 url 21959 } = partialFromXhr(); // The body will be read out if present. 21960 21961 let body = null; 21962 21963 if (status !== 204 21964 /* HttpStatusCode.NoContent */ 21965 ) { 21966 // Use XMLHttpRequest.response if set, responseText otherwise. 21967 body = typeof xhr.response === 'undefined' ? xhr.responseText : xhr.response; 21968 } // Normalize another potential bug (this one comes from CORS). 21969 21970 21971 if (status === 0) { 21972 status = !!body ? 200 21973 /* HttpStatusCode.Ok */ 21974 : 0; 21975 } // ok determines whether the response will be transmitted on the event or 21976 // error channel. Unsuccessful status codes (not 2xx) will always be errors, 21977 // but a successful status code can still result in an error if the user 21978 // asked for JSON data and the body cannot be parsed as such. 21979 21980 21981 let ok = status >= 200 && status < 300; // Check whether the body needs to be parsed as JSON (in many cases the browser 21982 // will have done that already). 21983 21984 if (req.responseType === 'json' && typeof body === 'string') { 21985 // Save the original body, before attempting XSSI prefix stripping. 21986 const originalBody = body; 21987 body = body.replace(XSSI_PREFIX, ''); 21988 21989 try { 21990 // Attempt the parse. If it fails, a parse error should be delivered to the user. 21991 body = body !== '' ? JSON.parse(body) : null; 21992 } catch (error) { 21993 // Since the JSON.parse failed, it's reasonable to assume this might not have been a 21994 // JSON response. Restore the original body (including any XSSI prefix) to deliver 21995 // a better error response. 21996 body = originalBody; // If this was an error request to begin with, leave it as a string, it probably 21997 // just isn't JSON. Otherwise, deliver the parsing error to the user. 21998 21999 if (ok) { 22000 // Even though the response status was 2xx, this is still an error. 22001 ok = false; // The parse error contains the text of the body that failed to parse. 22002 22003 body = { 22004 error, 22005 text: body 22006 }; 22007 } 22008 } 22009 } 22010 22011 if (ok) { 22012 // A successful response is delivered on the event stream. 22013 observer.next(new HttpResponse({ 22014 body, 22015 headers, 22016 status, 22017 statusText, 22018 url: url || undefined 22019 })); // The full body has been received and delivered, no further events 22020 // are possible. This request is complete. 22021 22022 observer.complete(); 22023 } else { 22024 // An unsuccessful request is delivered on the error channel. 22025 observer.error(new HttpErrorResponse({ 22026 // The error in this case is the response body (error from the server). 22027 error: body, 22028 headers, 22029 status, 22030 statusText, 22031 url: url || undefined 22032 })); 22033 } 22034 }; // The onError callback is called when something goes wrong at the network level. 22035 // Connection timeout, DNS error, offline, etc. These are actual errors, and are 22036 // transmitted on the error channel. 22037 22038 22039 const onError = error => { 22040 const { 22041 url 22042 } = partialFromXhr(); 22043 const res = new HttpErrorResponse({ 22044 error, 22045 status: xhr.status || 0, 22046 statusText: xhr.statusText || 'Unknown Error', 22047 url: url || undefined 22048 }); 22049 observer.error(res); 22050 }; // The sentHeaders flag tracks whether the HttpResponseHeaders event 22051 // has been sent on the stream. This is necessary to track if progress 22052 // is enabled since the event will be sent on only the first download 22053 // progress event. 22054 22055 22056 let sentHeaders = false; // The download progress event handler, which is only registered if 22057 // progress events are enabled. 22058 22059 const onDownProgress = event => { 22060 // Send the HttpResponseHeaders event if it hasn't been sent already. 22061 if (!sentHeaders) { 22062 observer.next(partialFromXhr()); 22063 sentHeaders = true; 22064 } // Start building the download progress event to deliver on the response 22065 // event stream. 22066 22067 22068 let progressEvent = { 22069 type: HttpEventType.DownloadProgress, 22070 loaded: event.loaded 22071 }; // Set the total number of bytes in the event if it's available. 22072 22073 if (event.lengthComputable) { 22074 progressEvent.total = event.total; 22075 } // If the request was for text content and a partial response is 22076 // available on XMLHttpRequest, include it in the progress event 22077 // to allow for streaming reads. 22078 22079 22080 if (req.responseType === 'text' && !!xhr.responseText) { 22081 progressEvent.partialText = xhr.responseText; 22082 } // Finally, fire the event. 22083 22084 22085 observer.next(progressEvent); 22086 }; // The upload progress event handler, which is only registered if 22087 // progress events are enabled. 22088 22089 22090 const onUpProgress = event => { 22091 // Upload progress events are simpler. Begin building the progress 22092 // event. 22093 let progress = { 22094 type: HttpEventType.UploadProgress, 22095 loaded: event.loaded 22096 }; // If the total number of bytes being uploaded is available, include 22097 // it. 22098 22099 if (event.lengthComputable) { 22100 progress.total = event.total; 22101 } // Send the event. 22102 22103 22104 observer.next(progress); 22105 }; // By default, register for load and error events. 22106 22107 22108 xhr.addEventListener('load', onLoad); 22109 xhr.addEventListener('error', onError); 22110 xhr.addEventListener('timeout', onError); 22111 xhr.addEventListener('abort', onError); // Progress events are only enabled if requested. 22112 22113 if (req.reportProgress) { 22114 // Download progress is always enabled if requested. 22115 xhr.addEventListener('progress', onDownProgress); // Upload progress depends on whether there is a body to upload. 22116 22117 if (reqBody !== null && xhr.upload) { 22118 xhr.upload.addEventListener('progress', onUpProgress); 22119 } 22120 } // Fire the request, and notify the event stream that it was fired. 22121 22122 22123 xhr.send(reqBody); 22124 observer.next({ 22125 type: HttpEventType.Sent 22126 }); // This is the return from the Observable function, which is the 22127 // request cancellation handler. 22128 22129 return () => { 22130 // On a cancellation, remove all registered event listeners. 22131 xhr.removeEventListener('error', onError); 22132 xhr.removeEventListener('abort', onError); 22133 xhr.removeEventListener('load', onLoad); 22134 xhr.removeEventListener('timeout', onError); 22135 22136 if (req.reportProgress) { 22137 xhr.removeEventListener('progress', onDownProgress); 22138 22139 if (reqBody !== null && xhr.upload) { 22140 xhr.upload.removeEventListener('progress', onUpProgress); 22141 } 22142 } // Finally, abort the in-flight request. 22143 22144 22145 if (xhr.readyState !== xhr.DONE) { 22146 xhr.abort(); 22147 } 22148 }; 22149 }); 22150 } 22151 22152} 22153 22154HttpXhrBackend.ɵfac = function HttpXhrBackend_Factory(t) { 22155 return new (t || HttpXhrBackend)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_6__.XhrFactory)
22155); 22156}; 22157 22158HttpXhrBackend.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({ 22159 token: HttpXhrBackend, 22160 factory: HttpXhrBackend.ɵfac 22161}); 22162 22163(function () { 22164 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpXhrBackend, [{ 22165 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable 22166 }], function () { 22167 return [{ 22168 type: _angular_common__WEBPACK_IMPORTED_MODULE_6__.XhrFactory 22169 }]; 22170 }, null); 22171})(); 22172/** 22173 * @license 22174 * Copyright Google LLC All Rights Reserved. 22175 * 22176 * Use of this source code is governed by an MIT-style license that can be 22177 * found in the LICENSE file at https://angular.io/license 22178 */ 22179 22180 22181const XSRF_COOKIE_NAME = new _angular_core__WEBPACK_IMPORTED_MODULE_4__.InjectionToken('XSRF_COOKIE_NAME'); 22182const XSRF_HEADER_NAME = new _angular_core__WEBPACK_IMPORTED_MODULE_4__.InjectionToken('XSRF_HEADER_NAME'); 22183/** 22184 * Retrieves the current XSRF token to use with the next outgoing request. 22185 * 22186 * @publicApi 22187 */ 22188 22189class HttpXsrfTokenExtractor {} 22190/** 22191 * `HttpXsrfTokenExtractor` which retrieves the token from a cookie. 22192 */ 22193 22194 22195class HttpXsrfCookieExtractor { 22196 constructor(doc, platform, cookieName) { 22197 this.doc = doc; 22198 this.platform = platform; 22199 this.cookieName = cookieName; 22200 this.lastCookieString = ''; 22201 this.lastToken = null; 22202 /** 22203 * @internal for testing 22204 */ 22205 22206 this.parseCount = 0; 22207 } 22208 22209 getToken() { 22210 if (this.platform === 'server') { 22211 return null; 22212 } 22213 22214 const cookieString = this.doc.cookie || ''; 22215 22216 if (cookieString !== this.lastCookieString) { 22217 this.parseCount++; 22218 this.lastToken = (0,_angular_common__WEBPACK_IMPORTED_MODULE_6__["ɵparseCookieValue"])(cookieString, this.cookieName); 22219 this.lastCookieString = cookieString; 22220 } 22221 22222 return this.lastToken; 22223 } 22224 22225} 22226 22227HttpXsrfCookieExtractor.ɵfac = function HttpXsrfCookieExtractor_Factory(t) { 22228 return new (t || HttpXsrfCookieExtractor)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_6__.DOCUMENT), _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_4__.PLATFORM_ID), _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](XSRF_COOKIE_NAME)); 22229}; 22230 22231HttpXsrfCookieExtractor.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({ 22232 token: HttpXsrfCookieExtractor, 22233 factory: HttpXsrfCookieExtractor.ɵfac 22234}); 22235 22236(function () { 22237 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpXsrfCookieExtractor, [{ 22238 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable 22239 }], function () { 22240 return [{ 22241 type: undefined, 22242 decorators: [{ 22243 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Inject, 22244 args: [_angular_common__WEBPACK_IMPORTED_MODULE_6__.DOCUMENT] 22245 }] 22246 }, { 22247 type: undefined, 22248 decorators: [{ 22249 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Inject, 22250 args: [_angular_core__WEBPACK_IMPORTED_MODULE_4__.PLATFORM_ID] 22251 }] 22252 }, { 22253 type: undefined, 22254 decorators: [{ 22255 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Inject, 22256 args: [XSRF_COOKIE_NAME] 22257 }] 22258 }]; 22259 }, null); 22260})(); 22261/** 22262 * `HttpInterceptor` which adds an XSRF token to eligible outgoing requests. 22263 */ 22264 22265 22266class HttpXsrfInterceptor { 22267 constructor(tokenService, headerName) { 22268 this.tokenService = tokenService; 22269 this.headerName = headerName; 22270 } 22271 22272 intercept(req, next) { 22273 const lcUrl = req.url.toLowerCase(); // Skip both non-mutating requests and absolute URLs. 22274 // Non-mutating requests don't require a token, and absolute URLs require special handling 22275 // anyway as the cookie set 22276 // on our origin is not the same as the token expected by another origin. 22277 22278 if (req.method === 'GET' || req.method === 'HEAD' || lcUrl.startsWith('http://') || lcUrl.startsWith('https://')) { 22279 return next.handle(req); 22280 } 22281 22282 const token = this.tokenService.getToken(); // Be careful not to overwrite an existing header of the same name. 22283 22284 if (token !== null && !req.headers.has(this.headerName)) { 22285 req = req.clone({ 22286 headers: req.headers.set(this.headerName, token) 22287 }); 22288 } 22289 22290 return next.handle(req); 22291 } 22292 22293} 22294 22295HttpXsrfInterceptor.ɵfac = function HttpXsrfInterceptor_Factory(t) { 22296 return new (t || HttpXsrfInterceptor)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](HttpXsrfTokenExtractor), _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](XSRF_HEADER_NAME)); 22297}; 22298 22299HttpXsrfInterceptor.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({ 22300 token: HttpXsrfInterceptor, 22301 factory: HttpXsrfInterceptor.ɵfac 22302}); 22303 22304(function () { 22305 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpXsrfInterceptor, [{ 22306 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable 22307 }], function () { 22308 return [{ 22309 type: HttpXsrfTokenExtractor 22310 }, {
22311 type: undefined, 22312 decorators: [{ 22313 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Inject, 22314 args: [XSRF_HEADER_NAME] 22315 }] 22316 }]; 22317 }, null); 22318})(); 22319/** 22320 * @license 22321 * Copyright Google LLC All Rights Reserved. 22322 * 22323 * Use of this source code is governed by an MIT-style license that can be 22324 * found in the LICENSE file at https://angular.io/license 22325 */ 22326 22327/** 22328 * An injectable `HttpHandler` that applies multiple interceptors 22329 * to a request before passing it to the given `HttpBackend`. 22330 * 22331 * The interceptors are loaded lazily from the injector, to allow 22332 * interceptors to themselves inject classes depending indirectly 22333 * on `HttpInterceptingHandler` itself. 22334 * @see `HttpInterceptor` 22335 */ 22336 22337 22338class HttpInterceptingHandler { 22339 constructor(backend, injector) { 22340 this.backend = backend; 22341 this.injector = injector; 22342 this.chain = null; 22343 } 22344 22345 handle(req) { 22346 if (this.chain === null) { 22347 const interceptors = this.injector.get(HTTP_INTERCEPTORS, []); 22348 this.chain = interceptors.reduceRight((next, interceptor) => new HttpInterceptorHandler(next, interceptor), this.backend); 22349 } 22350 22351 return this.chain.handle(req); 22352 } 22353 22354} 22355 22356HttpInterceptingHandler.ɵfac = function HttpInterceptingHandler_Factory(t) { 22357 return new (t || HttpInterceptingHandler)(_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](HttpBackend), _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_4__.Injector)); 22358}; 22359 22360HttpInterceptingHandler.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjectable"]({ 22361 token: HttpInterceptingHandler, 22362 factory: HttpInterceptingHandler.ɵfac 22363}); 22364 22365(function () { 22366 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpInterceptingHandler, [{ 22367 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injectable 22368 }], function () { 22369 return [{ 22370 type: HttpBackend 22371 }, { 22372 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.Injector 22373 }]; 22374 }, null); 22375})(); 22376/** 22377 * Constructs an `HttpHandler` that applies interceptors 22378 * to a request before passing it to the given `HttpBackend`. 22379 * 22380 * Use as a factory function within `HttpClientModule`. 22381 * 22382 * 22383 */ 22384 22385 22386function interceptingHandler(backend, interceptors = []) { 22387 if (!interceptors) { 22388 return backend; 22389 } 22390 22391 return interceptors.reduceRight((next, interceptor) => new HttpInterceptorHandler(next, interceptor), backend); 22392} 22393/** 22394 * Factory function that determines where to store JSONP callbacks. 22395 * 22396 * Ordinarily JSONP callbacks are stored on the `window` object, but this may not exist 22397 * in test environments. In that case, callbacks are stored on an anonymous object instead. 22398 * 22399 * 22400 */ 22401 22402 22403function jsonpCallbackContext() { 22404 if (typeof window === 'object') { 22405 return window; 22406 } 22407 22408 return {}; 22409} 22410/** 22411 * Configures XSRF protection support for outgoing requests. 22412 * 22413 * For a server that supports a cookie-based XSRF protection system, 22414 * use directly to configure XSRF protection with the correct 22415 * cookie and header names. 22416 * 22417 * If no names are supplied, the default cookie name is `XSRF-TOKEN` 22418 * and the default header name is `X-XSRF-TOKEN`. 22419 * 22420 * @publicApi 22421 */ 22422 22423 22424class HttpClientXsrfModule { 22425 /** 22426 * Disable the default XSRF protection. 22427 */ 22428 static disable() { 22429 return { 22430 ngModule: HttpClientXsrfModule, 22431 providers: [{ 22432 provide: HttpXsrfInterceptor, 22433 useClass: NoopInterceptor 22434 }] 22435 }; 22436 } 22437 /** 22438 * Configure XSRF protection. 22439 * @param options An object that can specify either or both 22440 * cookie name or header name. 22441 * - Cookie name default is `XSRF-TOKEN`. 22442 * - Header name default is `X-XSRF-TOKEN`. 22443 * 22444 */ 22445 22446 22447 static withOptions(options = {}) { 22448 return { 22449 ngModule: HttpClientXsrfModule, 22450 providers: [options.cookieName ? { 22451 provide: XSRF_COOKIE_NAME, 22452 useValue: options.cookieName 22453 } : [], options.headerName ? { 22454 provide: XSRF_HEADER_NAME, 22455 useValue: options.headerName 22456 } : []] 22457 }; 22458 } 22459 22460} 22461 22462HttpClientXsrfModule.ɵfac = function HttpClientXsrfModule_Factory(t) { 22463 return new (t || HttpClientXsrfModule)(); 22464}; 22465 22466HttpClientXsrfModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineNgModule"]({ 22467 type: HttpClientXsrfModule 22468}); 22469HttpClientXsrfModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjector"]({ 22470 providers: [HttpXsrfInterceptor, { 22471 provide: HTTP_INTERCEPTORS, 22472 useExisting: HttpXsrfInterceptor, 22473 multi: true 22474 }, { 22475 provide: HttpXsrfTokenExtractor, 22476 useClass: HttpXsrfCookieExtractor 22477 }, { 22478 provide: XSRF_COOKIE_NAME, 22479 useValue: 'XSRF-TOKEN' 22480 }, { 22481 provide: XSRF_HEADER_NAME, 22482 useValue: 'X-XSRF-TOKEN' 22483 }] 22484}); 22485 22486(function () { 22487 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpCl
22487ientXsrfModule, [{ 22488 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.NgModule, 22489 args: [{ 22490 providers: [HttpXsrfInterceptor, { 22491 provide: HTTP_INTERCEPTORS, 22492 useExisting: HttpXsrfInterceptor, 22493 multi: true 22494 }, { 22495 provide: HttpXsrfTokenExtractor, 22496 useClass: HttpXsrfCookieExtractor 22497 }, { 22498 provide: XSRF_COOKIE_NAME, 22499 useValue: 'XSRF-TOKEN' 22500 }, { 22501 provide: XSRF_HEADER_NAME, 22502 useValue: 'X-XSRF-TOKEN' 22503 }] 22504 }] 22505 }], null, null); 22506})(); 22507/** 22508 * Configures the [dependency injector](guide/glossary#injector) for `HttpClient` 22509 * with supporting services for XSRF. Automatically imported by `HttpClientModule`. 22510 * 22511 * You can add interceptors to the chain behind `HttpClient` by binding them to the 22512 * multiprovider for built-in [DI token](guide/glossary#di-token) `HTTP_INTERCEPTORS`. 22513 * 22514 * @publicApi 22515 */ 22516 22517 22518class HttpClientModule {} 22519 22520HttpClientModule.ɵfac = function HttpClientModule_Factory(t) { 22521 return new (t || HttpClientModule)(); 22522}; 22523 22524HttpClientModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineNgModule"]({ 22525 type: HttpClientModule, 22526 imports: [HttpClientXsrfModule] 22527}); 22528HttpClientModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjector"]({ 22529 providers: [HttpClient, { 22530 provide: HttpHandler, 22531 useClass: HttpInterceptingHandler 22532 }, HttpXhrBackend, { 22533 provide: HttpBackend, 22534 useExisting: HttpXhrBackend 22535 }], 22536 imports: [HttpClientXsrfModule.withOptions({ 22537 cookieName: 'XSRF-TOKEN', 22538 headerName: 'X-XSRF-TOKEN' 22539 })] 22540}); 22541 22542(function () { 22543 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpClientModule, [{ 22544 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.NgModule, 22545 args: [{ 22546 /** 22547 * Optional configuration for XSRF protection. 22548 */ 22549 imports: [HttpClientXsrfModule.withOptions({ 22550 cookieName: 'XSRF-TOKEN', 22551 headerName: 'X-XSRF-TOKEN' 22552 })], 22553 22554 /** 22555 * Configures the [dependency injector](guide/glossary#injector) where it is imported 22556 * with supporting services for HTTP communications. 22557 */ 22558 providers: [HttpClient, { 22559 provide: HttpHandler, 22560 useClass: HttpInterceptingHandler 22561 }, HttpXhrBackend, { 22562 provide: HttpBackend, 22563 useExisting: HttpXhrBackend 22564 }] 22565 }] 22566 }], null, null); 22567})(); 22568/** 22569 * Configures the [dependency injector](guide/glossary#injector) for `HttpClient` 22570 * with supporting services for JSONP. 22571 * Without this module, Jsonp requests reach the backend 22572 * with method JSONP, where they are rejected. 22573 * 22574 * You can add interceptors to the chain behind `HttpClient` by binding them to the 22575 * multiprovider for built-in [DI token](guide/glossary#di-token) `HTTP_INTERCEPTORS`. 22576 * 22577 * @publicApi 22578 */ 22579 22580 22581class HttpClientJsonpModule {} 22582 22583HttpClientJsonpModule.ɵfac = function HttpClientJsonpModule_Factory(t) { 22584 return new (t || HttpClientJsonpModule)(); 22585}; 22586 22587HttpClientJsonpModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineNgModule"]({ 22588 type: HttpClientJsonpModule 22589}); 22590HttpClientJsonpModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵɵdefineInjector"]({ 22591 providers: [JsonpClientBackend, { 22592 provide: JsonpCallbackContext, 22593 useFactory: jsonpCallbackContext 22594 }, { 22595 provide: HTTP_INTERCEPTORS, 22596 useClass: JsonpInterceptor, 22597 multi: true 22598 }] 22599}); 22600 22601(function () { 22602 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_4__["ɵsetClassMetadata"](HttpClientJsonpModule, [{ 22603 type: _angular_core__WEBPACK_IMPORTED_MODULE_4__.NgModule, 22604 args: [{ 22605 providers: [JsonpClientBackend, { 22606 provide: JsonpCallbackContext, 22607 useFactory: jsonpCallbackContext 22608 }, { 22609 provide: HTTP_INTERCEPTORS, 22610 useClass: JsonpInterceptor, 22611 multi: true 22612 }] 22613 }] 22614 }], null, null); 22615})(); 22616/** 22617 * @license 22618 * Copyright Google LLC All Rights Reserved. 22619 * 22620 * Use of this source code is governed by an MIT-style license that can be 22621 * found in the LICENSE file at https://angular.io/license 22622 */ 22623 22624/** 22625 * A wrapper around the `XMLHttpRequest` constructor. 22626 * 22627 * @publicApi 22628 * @see `XhrFactory` 22629 * @deprecated 22630 * `XhrFactory` has moved, please import `XhrFactory` from `@angular/common` instead. 22631 */ 22632 22633 22634const XhrFactory = _angular_common__WEBPACK_IMPORTED_MODULE_6__.XhrFactory; 22635/** 22636 * @license 22637 * Copyright Google LLC All Rights Reserved. 22638 * 22639 * Use of this source code is governed by an MIT-style license that can be 22640 * found in the LICENSE file at https://angular.io/license 22641 */ 22642 22643/** 22644 * Generated bundle index. Do not edit. 22645 */ 22646 22647 22648 22649/***/ }), 22650 22651/***/ 8781: 22652/*!**************************************************************!*\ 22653 !*** ./node_modules/@angular/compiler/fesm2020/compiler.mjs ***! 22654 \**************************************************************/ 22655/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 22656 22657__webpack_require__.r(__webpack_exports__); 22658/* harmony export */ __webpack_require__.d(__webpack_exports__, { 22659/* harmony export */ "AST": () => (/* binding */ AST), 22660/* harmony export */ "ASTWithName": () => (/* binding */ ASTWithName), 22661/* harmony export */ "ASTWithSource": () => (/* binding */ ASTWithSource), 22662/* harmony export */ "AbsoluteSourceSpan": () => (/* binding */ AbsoluteSourceSpan), 22663/* harmony export */ "ArrayType": () => (/* binding */ ArrayType), 22664/* harmony export */ "AstMemoryEfficientTransformer": () => (/* binding */ AstMemoryEfficientTransformer), 22665/* harmony export */ "AstTransformer": () => (/* binding */ AstTransformer), 22666/* harmony export */ "Attribute": () => (/* binding */ Attribute), 22667/* harmony export */ "Binary": () => (/* binding */ Binary), 22668/* harmony export */ "BinaryOperator": () => (/* binding */ BinaryOperator), 22669/* harmony export */ "BinaryOperatorExpr": () => (/* binding */ BinaryOperatorExpr), 22670/* harmony export */ "BindingPipe": () => (/* binding */ BindingPipe), 22671/* harmony export */ "BoundElementProperty": () => (/* binding */ BoundElementProperty), 22672/* harmony export */ "BuiltinType": () => (/* binding */ BuiltinType), 22673/* harmony export */ "BuiltinTypeName": () => (/* binding */ BuiltinTypeName), 22674/* harmony export */ "CUSTOM_ELEMENTS_SCHEMA": () => (/* binding */ CUSTOM_ELEMENTS_SCHEMA), 22675/* harmony export */ "Call": () => (/* binding */ Call), 22676/* harmony export */ "Chain": () => (/* binding */ Chain), 22677/* harmony export */ "ChangeDetectionStrategy": () => (/* binding */ ChangeDetectionStrategy), 22678/* harmony export */ "CommaExpr": () => (/* binding */ CommaExpr), 22679/* harmony export */ "Comment": () => (/* binding */ Comment), 22680/* harmony export */ "CompilerConfig": () => (/* binding */ CompilerConfig), 22681/* harmony export */ "Conditional": () => (/* binding */ Conditional), 22682/* harmony export */ "ConditionalExpr": () => (/* binding */ ConditionalExpr), 22683/* harmony export */ "ConstantPool": () => (/* binding */ ConstantPool), 22684/* harmony export */ "CssSelector": () => (/* binding */ CssSelector), 22685/* harmony export */ "DEFAULT_INTERPOLATION_CONFIG": () => (/* binding */ DEFAULT_INTERPOLATION_CONFIG),
22686/* harmony export */ "DYNAMIC_TYPE": () => (/* binding */ DYNAMIC_TYPE), 22687/* harmony export */ "DeclareFunctionStmt": () => (/* binding */ DeclareFunctionStmt), 22688/* harmony export */ "DeclareVarStmt": () => (/* binding */ DeclareVarStmt), 22689/* harmony export */ "DomElementSchemaRegistry": () => (/* binding */ DomElementSchemaRegistry), 22690/* harmony export */ "EOF": () => (/* binding */ EOF), 22691/* harmony export */ "Element": () => (/* binding */ Element), 22692/* harmony export */ "ElementSchemaRegistry": () => (/* binding */ ElementSchemaRegistry), 22693/* harmony export */ "EmitterVisitorContext": () => (/* binding */ EmitterVisitorContext), 22694/* harmony export */ "EmptyExpr": () => (/* binding */ EmptyExpr), 22695/* harmony export */ "Expansion": () => (/* binding */ Expansion), 22696/* harmony export */ "ExpansionCase": () => (/* binding */ ExpansionCase), 22697/* harmony export */ "Expression": () => (/* binding */ Expression), 22698/* harmony export */ "ExpressionBinding": () => (/* binding */ ExpressionBinding), 22699/* harmony export */ "ExpressionStatement": () => (/* binding */ ExpressionStatement), 22700/* harmony export */ "ExpressionType": () => (/* binding */ ExpressionType), 22701/* harmony export */ "ExternalExpr": () => (/* binding */ ExternalExpr), 22702/* harmony export */ "ExternalReference": () => (/* binding */ ExternalReference), 22703/* harmony export */ "FactoryTarget": () => (/* binding */ FactoryTarget$1), 22704/* harmony export */ "FunctionExpr": () => (/* binding */ FunctionExpr), 22705/* harmony export */ "HtmlParser": () => (/* binding */ HtmlParser), 22706/* harmony export */ "HtmlTagDefinition": () => (/* binding */ HtmlTagDefinition), 22707/* harmony export */ "I18NHtmlParser": () => (/* binding */ I18NHtmlParser), 22708/* harmony export */ "IfStmt": () => (/* binding */ IfStmt), 22709/* harmony export */ "ImplicitReceiver": () => (/* binding */ ImplicitReceiver), 22710/* harmony export */ "InstantiateExpr": () => (/* binding */ InstantiateExpr), 22711/* harmony export */ "Interpolation": () => (/* binding */ Interpolation), 22712/* harmony export */ "InterpolationConfig": () => (/* binding */ InterpolationConfig), 22713/* harmony export */ "InvokeFunctionExpr": () => (/* binding */ InvokeFunctionExpr), 22714/* harmony export */ "JSDocComment": () => (/* binding */ JSDocComment), 22715/* harmony export */ "JitEvaluator": () => (/* binding */ JitEvaluator), 22716/* harmony export */ "KeyedRead": () => (/* binding */ KeyedRead), 22717/* harmony export */ "KeyedWrite": () => (/* binding */ KeyedWrite), 22718/* harmony export */ "LeadingComment": () => (/* binding */ LeadingComment), 22719/* harmony export */ "Lexer": () => (/* binding */ Lexer), 22720/* harmony export */ "LiteralArray": () => (/* binding */ LiteralArray), 22721/* harmony export */ "LiteralArrayExpr": () => (/* binding */ LiteralArrayExpr), 22722/* harmony export */ "LiteralExpr": () => (/* binding */ LiteralExpr), 22723/* harmony export */ "LiteralMap": () => (/* binding */ LiteralMap), 22724/* harmony export */ "LiteralMapExpr": () => (/* binding */ LiteralMapExpr), 22725/* harmony export */ "LiteralPrimitive": () => (/* binding */ LiteralPrimitive), 22726/* harmony export */ "LocalizedString": () => (/* binding */ LocalizedString), 22727/* harmony export */ "MapType": () => (/* binding */ MapType), 22728/* harmony export */ "MessageBundle": () => (/* binding */ MessageBundle), 22729/* harmony export */ "NONE_TYPE": () => (/* binding */ NONE_TYPE), 22730/* harmony export */ "NO_ERRORS_SCHEMA": () => (/* binding */ NO_ERRORS_SCHEMA), 22731/* harmony export */ "NodeWithI18n": () => (/* binding */ NodeWithI18n), 22732/* harmony export */ "NonNullAssert": () => (/* binding */ NonNullAssert), 22733/* harmony export */ "NotExpr": () => (/* binding */ NotExpr), 22734/* harmony export */ "ParseError": () => (/* binding */ ParseError), 22735/* harmony export */ "ParseErrorLevel": () => (/* binding */ ParseErrorLevel), 22736/* harmony export */ "ParseLocation": () => (/* binding */ ParseLocation), 22737/* harmony export */ "ParseSourceFile": () => (/* binding */ ParseSourceFile), 22738/* harmony export */ "ParseSourceSpan": () => (/* binding */ ParseSourceSpan), 22739/* harmony export */ "ParseSpan": () => (/* binding */ ParseSpan), 22740/* harmony export */ "ParseTreeResult": () => (/* binding */ ParseTreeResult), 22741/* harmony export */ "ParsedEvent": () => (/* binding */ ParsedEvent), 22742/* harmony export */ "ParsedProperty": () => (/* binding */ ParsedProperty), 22743/* harmony export */ "ParsedPropertyType": () => (/* binding */ ParsedPropertyType), 22744/* harmony export */ "ParsedVariable": () => (/* binding */ ParsedVariable), 22745/* harmony export */ "Parser": () => (/* binding */ Parser$1), 22746/* harmony export */ "ParserError": () => (/* binding */ ParserError), 22747/* harmony export */ "PrefixNot": () => (/* binding */ PrefixNot), 22748/* harmony export */ "PropertyRead": () => (/* binding */ PropertyRead), 22749/* harmony export */ "PropertyWrite": () => (/* binding */ PropertyWrite), 22750/* harmony export */ "R3BoundTarget": () => (/* binding */ R3BoundTarget), 22751/* harmony export */ "R3Identifiers": () => (/* binding */ Identifiers), 22752/* harmony export */ "R3SelectorScopeMode": () => (/* binding */ R3SelectorScopeMode), 22753/* harmony export */ "R3TargetBinder": () => (/* binding */ R3TargetBinder), 22754/* harmony export */ "R3TemplateDependencyKind": () => (/* binding */ R3TemplateDependencyKind), 22755/* harmony export */ "ReadKeyExpr": () => (/* binding */ ReadKeyExpr),
22756/* harmony export */ "ReadPropExpr": () => (/* binding */ ReadPropExpr), 22757/* harmony export */ "ReadVarExpr": () => (/* binding */ ReadVarExpr), 22758/* harmony export */ "RecursiveAstVisitor": () => (/* binding */ RecursiveAstVisitor), 22759/* harmony export */ "RecursiveVisitor": () => (/* binding */ RecursiveVisitor), 22760/* harmony export */ "ResourceLoader": () => (/* binding */ ResourceLoader), 22761/* harmony export */ "ReturnStatement": () => (/* binding */ ReturnStatement), 22762/* harmony export */ "STRING_TYPE": () => (/* binding */ STRING_TYPE), 22763/* harmony export */ "SafeCall": () => (/* binding */ SafeCall), 22764/* harmony export */ "SafeKeyedRead": () => (/* binding */ SafeKeyedRead), 22765/* harmony export */ "SafePropertyRead": () => (/* binding */ SafePropertyRead), 22766/* harmony export */ "SelectorContext": () => (/* binding */ SelectorContext), 22767/* harmony export */ "SelectorListContext": () => (/* binding */ SelectorListContext), 22768/* harmony export */ "SelectorMatcher": () => (/* binding */ SelectorMatcher), 22769/* harmony export */ "Serializer": () => (/* binding */ Serializer), 22770/* harmony export */ "SplitInterpolation": () => (/* binding */ SplitInterpolation), 22771/* harmony export */ "Statement": () => (/* binding */ Statement), 22772/* harmony export */ "StmtModifier": () => (/* binding */ StmtModifier), 22773/* harmony export */ "TagContentType": () => (/* binding */ TagContentType), 22774/* harmony export */ "TaggedTemplateExpr": () => (/* binding */ TaggedTemplateExpr), 22775/* harmony export */ "TemplateBindingParseResult": () => (/* binding */ TemplateBindingParseResult), 22776/* harmony export */ "TemplateLiteral": () => (/* binding */ TemplateLiteral), 22777/* harmony export */ "TemplateLiteralElement": () => (/* binding */ TemplateLiteralElement), 22778/* harmony export */ "Text": () => (/* binding */ Text), 22779/* harmony export */ "ThisReceiver": () => (/* binding */ ThisReceiver), 22780/* harmony export */ "TmplAstBoundAttribute": () => (/* binding */ BoundAttribute), 22781/* harmony export */ "TmplAstBoundEvent": () => (/* binding */ BoundEvent), 22782/* harmony export */ "TmplAstBoundText": () => (/* binding */ BoundText), 22783/* harmony export */ "TmplAstContent": () => (/* binding */ Content), 22784/* harmony export */ "TmplAstElement": () => (/* binding */ Element$1), 22785/* harmony export */ "TmplAstIcu": () => (/* binding */ Icu$1), 22786/* harmony export */ "TmplAstRecursiveVisitor": () => (/* binding */ RecursiveVisitor$1), 22787/* harmony export */ "TmplAstReference": () => (/* binding */ Reference), 22788/* harmony export */ "TmplAstTemplate": () => (/* binding */ Template), 22789/* harmony export */ "TmplAstText": () => (/* binding */ Text$3), 22790/* harmony export */ "TmplAstTextAttribute": () => (/* binding */ TextAttribute), 22791/* harmony export */ "TmplAstVariable": () => (/* binding */ Variable), 22792/* harmony export */ "Token": () => (/* binding */ Token), 22793/* harmony export */ "TokenType": () => (/* binding */ TokenType), 22794/* harmony export */ "TreeError": () => (/* binding */ TreeError), 22795/* harmony export */ "Type": () => (/* binding */ Type), 22796/* harmony export */ "TypeModifier": () => (/* binding */ TypeModifier), 22797/* harmony export */ "TypeofExpr": () => (/* binding */ TypeofExpr), 22798/* harmony export */ "Unary": () => (/* binding */ Unary), 22799/* harmony export */ "UnaryOperator": () => (/* binding */ UnaryOperator), 22800/* harmony export */ "UnaryOperatorExpr": () => (/* binding */ UnaryOperatorExpr), 22801/* harmony export */ "VERSION": () => (/* binding */ VERSION), 22802/* harmony export */ "VariableBinding": () => (/* binding */ VariableBinding), 22803/* harmony export */ "Version": () => (/* binding */ Version), 22804/* harmony export */ "ViewEncapsulation": () => (/* binding */ ViewEncapsulation), 22805/* harmony export */ "WrappedNodeExpr": () => (/* binding */ WrappedNodeExpr), 22806/* harmony export */ "WriteKeyExpr": () => (/* binding */ WriteKeyExpr), 22807/* harmony export */ "WritePropExpr": () => (/* binding */ WritePropExpr),
22808/* harmony export */ "WriteVarExpr": () => (/* binding */ WriteVarExpr), 22809/* harmony export */ "Xliff": () => (/* binding */ Xliff), 22810/* harmony export */ "Xliff2": () => (/* binding */ Xliff2), 22811/* harmony export */ "Xmb": () => (/* binding */ Xmb), 22812/* harmony export */ "XmlParser": () => (/* binding */ XmlParser), 22813/* harmony export */ "Xtb": () => (/* binding */ Xtb), 22814/* harmony export */ "_ParseAST": () => (/* binding */ _ParseAST), 22815/* harmony export */ "compileClassMetadata": () => (/* binding */ compileClassMetadata), 22816/* harmony export */ "compileComponentFromMetadata": () => (/* binding */ compileComponentFromMetadata), 22817/* harmony export */ "compileDeclareClassMetadata": () => (/* binding */ compileDeclareClassMetadata), 22818/* harmony export */ "compileDeclareComponentFromMetadata": () => (/* binding */ compileDeclareComponentFromMetadata), 22819/* harmony export */ "compileDeclareDirectiveFromMetadata": () => (/* binding */ compileDeclareDirectiveFromMetadata), 22820/* harmony export */ "compileDeclareFactoryFunction": () => (/* binding */ compileDeclareFactoryFunction), 22821/* harmony export */ "compileDeclareInjectableFromMetadata": () => (/* binding */ compileDeclareInjectableFromMetadata), 22822/* harmony export */ "compileDeclareInjectorFromMetadata": () => (/* binding */ compileDeclareInjectorFromMetadata), 22823/* harmony export */ "compileDeclareNgModuleFromMetadata": () => (/* binding */ compileDeclareNgModuleFromMetadata), 22824/* harmony export */ "compileDeclarePipeFromMetadata": () => (/* binding */ compileDeclarePipeFromMetadata), 22825/* harmony export */ "compileDirectiveFromMetadata": () => (/* binding */ compileDirectiveFromMetadata), 22826/* harmony export */ "compileFactoryFunction": () => (/* binding */ compileFactoryFunction), 22827/* harmony export */ "compileInjectable": () => (/* binding */ compileInjectable), 22828/* harmony export */ "compileInjector": () => (/* binding */ compileInjector), 22829/* harmony export */ "compileNgModule": () => (/* binding */ compileNgModule), 22830/* harmony export */ "compilePipeFromMetadata": () => (/* binding */ compilePipeFromMetadata), 22831/* harmony export */ "computeMsgId": () => (/* binding */ computeMsgId), 22832/* harmony export */ "core": () => (/* binding */ core), 22833/* harmony export */ "createInjectableType": () => (/* binding */ createInjectableType), 22834/* harmony export */ "createMayBeForwardRefExpression": () => (/* binding */ createMayBeForwardRefExpression), 22835/* harmony export */ "devOnlyGuardedExpression": () => (/* binding */ devOnlyGuardedExpression), 22836/* harmony export */ "emitDistinctChangesOnlyDefaultValue": () => (/* binding */ emitDistinctChangesOnlyDefaultValue), 22837/* harmony export */ "getHtmlTagDefinition": () => (/* binding */ getHtmlTagDefinition), 22838/* harmony export */ "getNsPrefix": () => (/* binding */ getNsPrefix), 22839/* harmony export */ "getSafePropertyAccessString": () => (/* binding */ getSafePropertyAccessString), 22840/* harmony export */ "identifierName": () => (/* binding */ identifierName), 22841/* harmony export */ "isIdentifier": () => (/* binding */ isIdentifier), 22842/* harmony export */ "isNgContainer": () => (/* binding */ isNgContainer), 22843/* harmony export */ "isNgContent": () => (/* binding */ isNgContent), 22844/* harmony export */ "isNgTemplate": () => (/* binding */ isNgTemplate), 22845/* harmony export */ "jsDocComment": () => (/* binding */ jsDocComment), 22846/* harmony export */ "leadingComment": () => (/* binding */ leadingComment), 22847/* harmony export */ "literalMap": () => (/* binding */ literalMap), 22848/* harmony export */ "makeBindingParser": () => (/* binding */ makeBindingParser), 22849/* harmony export */ "mergeNsAndName": () => (/* binding */ mergeNsAndName), 22850/* harmony export */ "outputAst": () => (/* binding */ output_ast), 22851/* harmony export */ "parseHostBindings": () => (/* binding */ parseHostBindings), 22852/* harmony export */ "parseTemplate": () => (/* binding */ parseTemplate), 22853/* harmony export */ "preserveWhitespacesDefault": () => (/* binding */ preserveWhitespacesDefault), 22854/* harmony export */ "publishFacade": () => (/* binding */ publishFacade), 22855/* harmony export */ "r3JitTypeSourceSpan": () => (/* binding */ r3JitTypeSourceSpan), 22856/* harmony export */ "sanitizeIdentifier": () => (/* binding */ sanitizeIdentifier), 22857/* harmony export */ "splitNsName": () => (/* binding */ splitNsName), 22858/* harmony export */ "verifyHostBindings": () => (/* binding */ verifyHostBindings), 22859/* harmony export */ "visitAll": () => (/* binding */ visitAll) 22860/* harmony export */ }); 22861/** 22862 * @license Angular v14.2.10 22863 * (c) 2010-2022 Google LLC. https://angular.io/ 22864 * License: MIT 22865 */ 22866 22867/** 22868 * @license 22869 * Copyright Google LLC All Rights Reserved. 22870 * 22871 * Use of this source code is governed by an MIT-style license that can be 22872 * found in the LICENSE file at https://angular.io/license 22873 */ 22874var TagContentType; 22875 22876(function (TagContentType) { 22877 TagContentType[TagContentType["RAW_TEXT"] = 0] = "RAW_TEXT"; 22878 TagContentType[TagContentType["ESCAPABLE_RAW_TEXT"] = 1] = "ESCAPABLE_RAW_TEXT"; 22879 TagContentType[TagContentType["PARSABLE_DATA"] = 2] = "PARSABLE_DATA"; 22880})(TagContentType || (TagContentType = {})); 22881 22882function splitNsName(elementName) { 22883 if (elementName[0] != ':') { 22884 return [null, elementName]; 22885 } 22886 22887 const colonIndex = elementName.indexOf(':', 1); 22888 22889 if (colonIndex === -1) { 22890 throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`); 22891 } 22892 22893 return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)]; 22894} // `<ng-container>` tags work the same regardless the namespace 22895 22896 22897function isNgContainer(tagName) { 22898 return splitNsName(tagName)[1] === 'ng-container'; 22899} // `<ng-content>` tags work the same regardless the namespace 22900 22901 22902function isNgContent(tagName) { 22903 return splitNsName(tagName)[1] === 'ng-content'; 22904} // `<ng-template>` tags work the same regardless the namespace 22905 22906 22907function isNgTemplate(tagName) { 22908 return splitNsName(tagName)[1] === 'ng-template'; 22909} 22910 22911function getNsPrefix(fullName) { 22912 return fullName === null ? null : splitNsName(fullName)[0]; 22913} 22914 22915function mergeNsAndName(prefix, localName) { 22916 return prefix ? `:${prefix}:${localName}` : localName; 22917} 22918/** 22919 * @license 22920 * Copyright Google LLC All Rights Reserved. 22921 * 22922 * Use of this source code is governed by an MIT-style license that can be 22923 * found in the LICENSE file at https://angular.io/license 22924 */ 22925 22926 22927class HtmlTagDefinition { 22928 constructor({ 22929 closedByChildren, 22930 implicitNamespacePrefix, 22931 contentType = TagContentType.PARSABLE_DATA, 22932 closedByParent = false, 22933 isVoid = false, 22934 ignoreFirstLf = false, 22935 preventNamespaceInheritance = false 22936 }
22936 = {}) { 22937 this.closedByChildren = {}; 22938 this.closedByParent = false; 22939 this.canSelfClose = false; 22940 22941 if (closedByChildren && closedByChildren.length > 0) { 22942 closedByChildren.forEach(tagName => this.closedByChildren[tagName] = true); 22943 } 22944 22945 this.isVoid = isVoid; 22946 this.closedByParent = closedByParent || isVoid; 22947 this.implicitNamespacePrefix = implicitNamespacePrefix || null; 22948 this.contentType = contentType; 22949 this.ignoreFirstLf = ignoreFirstLf; 22950 this.preventNamespaceInheritance = preventNamespaceInheritance; 22951 } 22952 22953 isClosedByChild(name) { 22954 return this.isVoid || name.toLowerCase() in this.closedByChildren; 22955 } 22956 22957 getContentType(prefix) { 22958 if (typeof this.contentType === 'object') { 22959 const overrideType = prefix === undefined ? undefined : this.contentType[prefix]; 22960 return overrideType ?? this.contentType.default; 22961 } 22962 22963 return this.contentType; 22964 } 22965 22966} 22967 22968let _DEFAULT_TAG_DEFINITION; // see https://www.w3.org/TR/html51/syntax.html#optional-tags 22969// This implementation does not fully conform to the HTML5 spec. 22970 22971 22972let TAG_DEFINITIONS; 22973 22974function getHtmlTagDefinition(tagName) { 22975 if (!TAG_DEFINITIONS) { 22976 _DEFAULT_TAG_DEFINITION = new HtmlTagDefinition(); 22977 TAG_DEFINITIONS = { 22978 'base': new HtmlTagDefinition({ 22979 isVoid: true 22980 }), 22981 'meta': new HtmlTagDefinition({ 22982 isVoid: true 22983 }), 22984 'area': new HtmlTagDefinition({ 22985 isVoid: true 22986 }), 22987 'embed': new HtmlTagDefinition({ 22988 isVoid: true 22989 }), 22990 'link': new HtmlTagDefinition({ 22991 isVoid: true 22992 }), 22993 'img': new HtmlTagDefinition({ 22994 isVoid: true 22995 }), 22996 'input': new HtmlTagDefinition({ 22997 isVoid: true 22998 }), 22999 'param': new HtmlTagDefinition({ 23000 isVoid: true 23001 }), 23002 'hr': new HtmlTagDefinition({ 23003 isVoid: true 23004 }), 23005 'br': new HtmlTagDefinition({ 23006 isVoid: true 23007 }), 23008 'source': new HtmlTagDefinition({ 23009 isVoid: true 23010 }), 23011 'track': new HtmlTagDefinition({ 23012 isVoid: true 23013 }), 23014 'wbr': new HtmlTagDefinition({ 23015 isVoid: true 23016 }), 23017 'p': new HtmlTagDefinition({ 23018 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'], 23019 closedByParent: true 23020 }), 23021 'thead': new HtmlTagDefinition({ 23022 closedByChildren: ['tbody', 'tfoot'] 23023 }), 23024 'tbody': new HtmlTagDefinition({ 23025 closedByChildren: ['tbody', 'tfoot'], 23026 closedByParent: true 23027 }), 23028 'tfoot': new HtmlTagDefinition({ 23029 closedByChildren: ['tbody'], 23030 closedByParent: true 23031 }), 23032 'tr': new HtmlTagDefinition({ 23033 closedByChildren: ['tr'], 23034 closedByParent: true 23035 }), 23036 'td': new HtmlTagDefinition({ 23037 closedByChildren: ['td', 'th'], 23038 closedByParent: true 23039 }), 23040 'th': new HtmlTagDefinition({ 23041 closedByChildren: ['td', 'th'], 23042 closedByParent: true 23043 }), 23044 'col': new HtmlTagDefinition({ 23045 isVoid: true 23046 }), 23047 'svg': new HtmlTagDefinition({ 23048 implicitNamespacePrefix: 'svg' 23049 }), 23050 'foreignObject': new HtmlTagDefinition({ 23051 // Usually the implicit namespace here would be redundant since it will be inherited from 23052 // the parent `svg`, but we have to do it for `foreignObject`, because the way the parser 23053 // works is that the parent node of an end tag is its own start tag which means that 23054 // the `preventNamespaceInheritance` on `foreignObject` would have it default to the 23055 // implicit namespace which is `html`, unless specified otherwise. 23056 implicitNamespacePrefix: 'svg', 23057 // We want to prevent children of foreignObject from inheriting its namespace, because 23058 // the point of the element is to allow nodes from other namespaces to be inserted. 23059 preventNamespaceInheritance: true 23060 }), 23061 'math': new HtmlTagDefinition({ 23062 implicitNamespacePrefix: 'math' 23063 }), 23064 'li': new HtmlTagDefinition({ 23065 closedByChildren: ['li'], 23066 closedByParent: true 23067 }), 23068 'dt': new HtmlTagDefinition({ 23069 closedByChildren: ['dt', 'dd'] 23070 }), 23071 'dd': new HtmlTagDefinition({ 23072 closedByChildren: ['dt', 'dd'], 23073 closedByParent: true 23074 }), 23075 'rb': new HtmlTagDefinition({ 23076 closedByChildren: ['rb', 'rt', 'rtc', 'rp'], 23077 closedByParent: true 23078 }), 23079 'rt': new HtmlTagDefinition({ 23080 closedByChildren: ['rb', 'rt', 'rtc', 'rp'], 23081 closedByParent: true 23082 }), 23083 'rtc': new HtmlTagDefinition({ 23084 closedByChildren: ['rb', 'rtc', 'rp'], 23085 closedByParent: true 23086 }), 23087 'rp': new HtmlTagDefinition({ 23088 closedByChildren: ['rb', 'rt', 'rtc', 'rp'], 23089 closedByParent: true 23090 }), 23091 'optgroup': new HtmlTagDefinition({ 23092 closedByChildren: ['optgroup'], 23093 closedByParent: true 23094 }), 23095 'option': new HtmlTagDefinition({ 23096 closedByChildren: ['option', 'optgroup'], 23097 closedByParent: true 23098 }), 23099 'pre': new HtmlTagDefinition({ 23100 ignoreFirstLf: true 23101 }), 23102 'listing': new HtmlTagDefinition({ 23103 ignoreFirstLf: true 23104 }), 23105 'style': new HtmlTagDefinition({ 23106 contentType: TagContentType.RAW_TEXT 23107 }), 23108 'script': new HtmlTagDefinition({ 23109 contentType: TagContentType.RAW_TEXT 23110 }), 23111 'title': new HtmlTagDefinition({ 23112 // The browser supports two separate `title` tags which have to use
23113 // a different content type: `HTMLTitleElement` and `SVGTitleElement` 23114 contentType: { 23115 default: TagContentType.ESCAPABLE_RAW_TEXT, 23116 svg: TagContentType.PARSABLE_DATA 23117 } 23118 }), 23119 'textarea': new HtmlTagDefinition({ 23120 contentType: TagContentType.ESCAPABLE_RAW_TEXT, 23121 ignoreFirstLf: true 23122 }) 23123 }; 23124 } // We have to make both a case-sensitive and a case-insensitive lookup, because 23125 // HTML tag names are case insensitive, whereas some SVG tags are case sensitive. 23126 23127 23128 return TAG_DEFINITIONS[tagName] ?? TAG_DEFINITIONS[tagName.toLowerCase()] ?? _DEFAULT_TAG_DEFINITION; 23129} 23130/** 23131 * @license 23132 * Copyright Google LLC All Rights Reserved. 23133 * 23134 * Use of this source code is governed by an MIT-style license that can be 23135 * found in the LICENSE file at https://angular.io/license 23136 */ 23137 23138 23139const _SELECTOR_REGEXP = new RegExp('(\\:not\\()|' + // 1: ":not(" 23140'(([\\.\\#]?)[-\\w]+)|' + // 2: "tag"; 3: "."/"#"; 23141// "-" should appear first in the regexp below as FF31 parses "[.-\w]" as a range 23142// 4: attribute; 5: attribute_string; 6: attribute_value 23143'(?:\\[([-.\\w*\\\\$]+)(?:=([\"\']?)([^\\]\"\']*)\\5)?\\])|' + // "[name]", "[name=value]", 23144// "[name="value"]", 23145// "[name='value']" 23146'(\\))|' + // 7: ")" 23147'(\\s*,\\s*)', // 8: "," 23148'g'); 23149/** 23150 * A css selector contains an element name, 23151 * css classes and attribute/value pairs with the purpose 23152 * of selecting subsets out of them. 23153 */ 23154 23155 23156class CssSelector { 23157 constructor() { 23158 this.element = null; 23159 this.classNames = []; 23160 /** 23161 * The selectors are encoded in pairs where: 23162 * - even locations are attribute names 23163 * - odd locations are attribute values. 23164 * 23165 * Example: 23166 * Selector: `[key1=value1][key2]` would parse to: 23167 * ``` 23168 * ['key1', 'value1', 'key2', ''] 23169 * ``` 23170 */ 23171 23172 this.attrs = []; 23173 this.notSelectors = []; 23174 } 23175 23176 static parse(selector) { 23177 const results = []; 23178 23179 const _addResult = (res, cssSel) => { 23180 if (cssSel.notSelectors.length > 0 && !cssSel.element && cssSel.classNames.length == 0 && cssSel.attrs.length == 0) { 23181 cssSel.element = '*'; 23182 } 23183 23184 res.push(cssSel); 23185 }; 23186 23187 let cssSelector = new CssSelector(); 23188 let match; 23189 let current = cssSelector; 23190 let inNot = false; 23191 _SELECTOR_REGEXP.lastIndex = 0; 23192 23193 while (match = _SELECTOR_REGEXP.exec(selector)) { 23194 if (match[1 23195 /* SelectorRegexp.NOT */ 23196 ]) { 23197 if (inNot) { 23198 throw new Error('Nesting :not in a selector is not allowed'); 23199 } 23200 23201 inNot = true; 23202 current = new CssSelector(); 23203 cssSelector.notSelectors.push(current); 23204 } 23205 23206 const tag = match[2 23207 /* SelectorRegexp.TAG */ 23208 ]; 23209 23210 if (tag) { 23211 const prefix = match[3 23212 /* SelectorRegexp.PREFIX */ 23213 ]; 23214 23215 if (prefix === '#') { 23216 // #hash 23217 current.addAttribute('id', tag.slice(1)); 23218 } else if (prefix === '.') { 23219 // Class 23220 current.addClassName(tag.slice(1)); 23221 } else { 23222 // Element 23223 current.setElement(tag); 23224 } 23225 } 23226 23227 const attribute = match[4 23228 /* SelectorRegexp.ATTRIBUTE */ 23229 ]; 23230 23231 if (attribute) { 23232 current.addAttribute(current.unescapeAttribute(attribute), match[6 23233 /* SelectorRegexp.ATTRIBUTE_VALUE */ 23234 ]); 23235 } 23236 23237 if (match[7 23238 /* SelectorRegexp.NOT_END */ 23239 ]) { 23240 inNot = false; 23241 current = cssSelector; 23242 } 23243 23244 if (match[8 23245 /* SelectorRegexp.SEPARATOR */ 23246 ]) { 23247 if (inNot) { 23248 throw new Error('Multiple selectors in :not are not supported'); 23249 } 23250 23251 _addResult(results, cssSelector); 23252 23253 cssSelector = current = new CssSelector(); 23254 } 23255 } 23256 23257 _addResult(results, cssSelector); 23258 23259 return results; 23260 } 23261 /** 23262 * Unescape `\$` sequences from the CSS attribute selector. 23263 * 23264 * This is needed because `$` can have a special meaning in CSS selectors, 23265 * but we might want to match an attribute that contains `$`. 23266 * [MDN web link for more 23267 * info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors). 23268 * @param attr the attribute to unescape. 23269 * @returns the unescaped string. 23270 */ 23271 23272 23273 unescapeAttribute(attr) { 23274 let result = ''; 23275 let escaping = false;
23276 23277 for (let i = 0; i < attr.length; i++) { 23278 const char = attr.charAt(i); 23279 23280 if (char === '\\') { 23281 escaping = true; 23282 continue; 23283 } 23284 23285 if (char === '$' && !escaping) { 23286 throw new Error(`Error in attribute selector "${attr}". ` + `Unescaped "$" is not supported. Please escape with "\\$".`); 23287 } 23288 23289 escaping = false; 23290 result += char; 23291 } 23292 23293 return result; 23294 } 23295 /** 23296 * Escape `$` sequences from the CSS attribute selector. 23297 * 23298 * This is needed because `$` can have a special meaning in CSS selectors, 23299 * with this method we are escaping `$` with `\$'. 23300 * [MDN web link for more 23301 * info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors). 23302 * @param attr the attribute to escape. 23303 * @returns the escaped string. 23304 */ 23305 23306 23307 escapeAttribute(attr) { 23308 return attr.replace(/\\/g, '\\\\').replace(/\$/g, '\\$'); 23309 } 23310 23311 isElementSelector() { 23312 return this.hasElementSelector() && this.classNames.length == 0 && this.attrs.length == 0 && this.notSelectors.length === 0; 23313 } 23314 23315 hasElementSelector() { 23316 return !!this.element; 23317 } 23318 23319 setElement(element = null) { 23320 this.element = element; 23321 } 23322 /** Gets a template string for an element that matches the selector. */ 23323 23324 23325 getMatchingElementTemplate() { 23326 const tagName = this.element || 'div'; 23327 const classAttr = this.classNames.length > 0 ? ` class="${this.classNames.join(' ')}"` : ''; 23328 let attrs = ''; 23329 23330 for (let i = 0; i < this.attrs.length; i += 2) { 23331 const attrName = this.attrs[i]; 23332 const attrValue = this.attrs[i + 1] !== '' ? `="${this.attrs[i + 1]}"` : ''; 23333 attrs += ` ${attrName}${attrValue}`; 23334 } 23335 23336 return getHtmlTagDefinition(tagName).isVoid ? `<${tagName}${classAttr}${attrs}/>` : `<${tagName}${classAttr}${attrs}></${tagName}>`; 23337 } 23338 23339 getAttrs() { 23340 const result = []; 23341 23342 if (this.classNames.length > 0) { 23343 result.push('class', this.classNames.join(' ')); 23344 } 23345 23346 return result.concat(this.attrs); 23347 } 23348 23349 addAttribute(name, value = '') { 23350 this.attrs.push(name, value && value.toLowerCase() || ''); 23351 } 23352 23353 addClassName(name) { 23354 this.classNames.push(name.toLowerCase()); 23355 } 23356 23357 toString() { 23358 let res = this.element || ''; 23359 23360 if (this.classNames) { 23361 this.classNames.forEach(klass => res += `.${klass}`); 23362 } 23363 23364 if (this.attrs) { 23365 for (let i = 0; i < this.attrs.length; i += 2) { 23366 const name = this.escapeAttribute(this.attrs[i]); 23367 const value = this.attrs[i + 1]; 23368 res += `[${name}${value ? '=' + value : ''}]`; 23369 } 23370 } 23371 23372 this.notSelectors.forEach(notSelector => res += `:not(${notSelector})`); 23373 return res; 23374 } 23375 23376} 23377/** 23378 * Reads a list of CssSelectors and allows to calculate which ones 23379 * are contained in a given CssSelector. 23380 */ 23381 23382 23383class SelectorMatcher { 23384 constructor() { 23385 this._elementMap = new Map(); 23386 this._elementPartialMap = new Map(); 23387 this._classMap = new Map(); 23388 this._classPartialMap = new Map(); 23389 this._attrValueMap = new Map(); 23390 this._attrValuePartialMap = new Map(); 23391 this._listContexts = []; 23392 } 23393 23394 static createNotMatcher(notSelectors) { 23395 const notMatcher = new SelectorMatcher(); 23396 notMatcher.addSelectables(notSelectors, null); 23397 return notMatcher; 23398 } 23399 23400 addSelectables(cssSelectors, callbackCtxt) { 23401 let listContext = null; 23402 23403 if (cssSelectors.length > 1) { 23404 listContext = new SelectorListContext(cssSelectors); 23405 23406 this._listContexts.push(listContext); 23407 } 23408 23409 for (let i = 0; i < cssSelectors.length; i++) { 23410 this._addSelectable(cssSelectors[i], callbackCtxt, listContext); 23411 } 23412 } 23413 /** 23414 * Add an object that can be found later on by calling `match`. 23415 * @param cssSelector A css selector 23416 * @param callbackCtxt An opaque object that will be given to the callback of the `match` function 23417 */ 23418 23419 23420 _addSelectable(cssSelector, callbackCtxt, listContext) { 23421 let matcher = this; 23422 const element = cssSelector.element; 23423 const classNames = cssSelector.classNames; 23424 const attrs = cssSelector.attrs; 23425 const selectable = new SelectorContext(cssSelector, callbackCtxt, listContext); 23426 23427 if (element) { 23428 const isTerminal = attrs.length === 0 && classNames.length === 0; 23429 23430 if (isTerminal) { 23431 this._addTerminal(matcher._elementMap, element, selectable); 23432 } else { 23433 matcher = this._addPartial(matcher._elementPartialMap, element); 23434 } 23435 } 23436 23437 if (classNames) { 23438 for (let i = 0; i < classNames.length; i++) { 23439 const isTerminal = attrs.length === 0 && i === classNames.length - 1; 23440 const className = classNames[i]; 23441 23442 if (isTerminal) { 23443 this._addTerminal(matcher._classMap, className, selectable); 23444 } else { 23445 matcher = this._addPartial(matcher._classPartialMap, className); 23446 } 23447 } 23448 } 23449 23450 if (attrs) { 23451 for (let i = 0; i < attrs.length; i += 2) { 23452 const isTerminal = i === attrs.length - 2; 23453 const name = attrs[i]; 23454 const value = attrs[i + 1]; 23455 23456 if (isTerminal) { 23457 const terminalMap = matcher._attrValueMap;
23458 let terminalValuesMap = terminalMap.get(name); 23459 23460 if (!terminalValuesMap) { 23461 terminalValuesMap = new Map(); 23462 terminalMap.set(name, terminalValuesMap); 23463 } 23464 23465 this._addTerminal(terminalValuesMap, value, selectable); 23466 } else { 23467 const partialMap = matcher._attrValuePartialMap; 23468 let partialValuesMap = partialMap.get(name); 23469 23470 if (!partialValuesMap) { 23471 partialValuesMap = new Map(); 23472 partialMap.set(name, partialValuesMap); 23473 } 23474 23475 matcher = this._addPartial(partialValuesMap, value); 23476 } 23477 } 23478 } 23479 } 23480 23481 _addTerminal(map, name, selectable) { 23482 let terminalList = map.get(name); 23483 23484 if (!terminalList) { 23485 terminalList = []; 23486 map.set(name, terminalList); 23487 } 23488 23489 terminalList.push(selectable); 23490 } 23491 23492 _addPartial(map, name) { 23493 let matcher = map.get(name); 23494 23495 if (!matcher) { 23496 matcher = new SelectorMatcher(); 23497 map.set(name, matcher); 23498 } 23499 23500 return matcher; 23501 } 23502 /** 23503 * Find the objects that have been added via `addSelectable` 23504 * whose css selector is contained in the given css selector. 23505 * @param cssSelector A css selector 23506 * @param matchedCallback This callback will be called with the object handed into `addSelectable` 23507 * @return boolean true if a match was found 23508 */ 23509 23510 23511 match(cssSelector, matchedCallback) { 23512 let result = false;
23513 const element = cssSelector.element; 23514 const classNames = cssSelector.classNames; 23515 const attrs = cssSelector.attrs; 23516 23517 for (let i = 0; i < this._listContexts.length; i++) { 23518 this._listContexts[i].alreadyMatched = false; 23519 } 23520 23521 result = this._matchTerminal(this._elementMap, element, cssSelector, matchedCallback) || result; 23522 result = this._matchPartial(this._elementPartialMap, element, cssSelector, matchedCallback) || result; 23523 23524 if (classNames) { 23525 for (let i = 0; i < classNames.length; i++) { 23526 const className = classNames[i]; 23527 result = this._matchTerminal(this._classMap, className, cssSelector, matchedCallback) || result; 23528 result = this._matchPartial(this._classPartialMap, className, cssSelector, matchedCallback) || result; 23529 } 23530 } 23531 23532 if (attrs) { 23533 for (let i = 0; i < attrs.length; i += 2) { 23534 const name = attrs[i]; 23535 const value = attrs[i + 1]; 23536 23537 const terminalValuesMap = this._attrValueMap.get(name); 23538 23539 if (value) { 23540 result = this._matchTerminal(terminalValuesMap, '', cssSelector, matchedCallback) || result; 23541 } 23542 23543 result = this._matchTerminal(terminalValuesMap, value, cssSelector, matchedCallback) || result; 23544 23545 const partialValuesMap = this._attrValuePartialMap.get(name); 23546 23547 if (value) { 23548 result = this._matchPartial(partialValuesMap, '', cssSelector, matchedCallback) || result; 23549 } 23550 23551 result = this._matchPartial(partialValuesMap, value, cssSelector, matchedCallback) || result; 23552 } 23553 } 23554 23555 return result; 23556 } 23557 /** @internal */ 23558 23559 23560 _matchTerminal(map, name, cssSelector, matchedCallback) { 23561 if (!map || typeof name !== 'string') { 23562 return false; 23563 } 23564 23565 let selectables = map.get(name) || []; 23566 const starSelectables = map.get('*'); 23567 23568 if (starSelectables) { 23569 selectables = selectables.concat(starSelectables); 23570 } 23571 23572 if (selectables.length === 0) { 23573 return false; 23574 } 23575 23576 let selectable; 23577 let result = false;
23578 23579 for (let i = 0; i < selectables.length; i++) { 23580 selectable = selectables[i]; 23581 result = selectable.finalize(cssSelector, matchedCallback) || result; 23582 } 23583 23584 return result; 23585 } 23586 /** @internal */ 23587 23588 23589 _matchPartial(map, name, cssSelector, matchedCallback) { 23590 if (!map || typeof name !== 'string') { 23591 return false; 23592 } 23593 23594 const nestedSelector = map.get(name); 23595 23596 if (!nestedSelector) { 23597 return false; 23598 } // TODO(perf): get rid of recursion and measure again 23599 // TODO(perf): don't pass the whole selector into the recursion, 23600 // but only the not processed parts 23601 23602 23603 return nestedSelector.match(cssSelector, matchedCallback); 23604 } 23605 23606} 23607 23608class SelectorListContext { 23609 constructor(selectors) { 23610 this.selectors = selectors; 23611 this.alreadyMatched = false; 23612 } 23613 23614} // Store context to pass back selector and context when a selector is matched 23615 23616 23617class SelectorContext { 23618 constructor(selector, cbContext, listContext) { 23619 this.selector = selector; 23620 this.cbContext = cbContext; 23621 this.listContext = listContext; 23622 this.notSelectors = selector.notSelectors; 23623 } 23624 23625 finalize(cssSelector, callback) { 23626 let result = true; 23627 23628 if (this.notSelectors.length > 0 && (!this.listContext || !this.listContext.alreadyMatched)) { 23629 const notMatcher = SelectorMatcher.createNotMatcher(this.notSelectors); 23630 result = !notMatcher.match(cssSelector, null); 23631 } 23632 23633 if (result && callback && (!this.listContext || !this.listContext.alreadyMatched)) { 23634 if (this.listContext) { 23635 this.listContext.alreadyMatched = true; 23636 } 23637 23638 callback(this.selector, this.cbContext); 23639 } 23640 23641 return result; 23642 } 23643 23644} 23645/** 23646 * @license 23647 * Copyright Google LLC All Rights Reserved. 23648 * 23649 * Use of this source code is governed by an MIT-style license that can be 23650 * found in the LICENSE file at https://angular.io/license 23651 */ 23652// Stores the default value of `emitDistinctChangesOnly` when the `emitDistinctChangesOnly` is not 23653// explicitly set. 23654 23655 23656const emitDistinctChangesOnlyDefaultValue = true; 23657var ViewEncapsulation; 23658 23659(function (ViewEncapsulation) { 23660 ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated"; // Historically the 1 value was for `Native` encapsulation which has been removed as of v11. 23661 23662 ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None"; 23663 ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom"; 23664})(ViewEncapsulation || (ViewEncapsulation = {})); 23665 23666var ChangeDetectionStrategy; 23667 23668(function (ChangeDetectionStrategy) { 23669 ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush"; 23670 ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default"; 23671})(ChangeDetectionStrategy || (ChangeDetectionStrategy = {})); 23672 23673const CUSTOM_ELEMENTS_SCHEMA = { 23674 name: 'custom-elements' 23675}; 23676const NO_ERRORS_SCHEMA = { 23677 name: 'no-errors-schema' 23678}; 23679const Type$1 = Function; 23680var SecurityContext; 23681 23682(function (SecurityContext) { 23683 SecurityContext[SecurityContext["NONE"] = 0] = "NONE"; 23684 SecurityContext[SecurityContext["HTML"] = 1] = "HTML"; 23685 SecurityContext[SecurityContext["STYLE"] = 2] = "STYLE"; 23686 SecurityContext[SecurityContext["SCRIPT"] = 3] = "SCRIPT"; 23687 SecurityContext[SecurityContext["URL"] = 4] = "URL"; 23688 SecurityContext[SecurityContext["RESOURCE_URL"] = 5] = "RESOURCE_URL"; 23689})(SecurityContext || (SecurityContext = {})); 23690 23691var MissingTranslationStrategy; 23692 23693(function (MissingTranslationStrategy) { 23694 MissingTranslationStrategy[MissingTranslationStrategy["Error"] = 0] = "Error"; 23695 MissingTranslationStrategy[MissingTranslationStrategy["Warning"] = 1] = "Warning"; 23696 MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore"; 23697})(MissingTranslationStrategy || (MissingTranslationStrategy = {})); 23698 23699function parserSelectorToSimpleSelector(selector) { 23700 const classes = selector.classNames && selector.classNames.length ? [8 23701 /* SelectorFlags.CLASS */ 23702 , ...selector.classNames] : []; 23703 const elementName = selector.element && selector.element !== '*' ? selector.element : ''; 23704 return [elementName, ...selector.attrs, ...classes]; 23705} 23706 23707function parserSelectorToNegativeSelector(selector) { 23708 const classes = selector.classNames && selector.classNames.length ? [8 23709 /* SelectorFlags.CLASS */ 23710 , ...selector.classNames] : []; 23711 23712 if (selector.element) { 23713 return [1 23714 /* SelectorFlags.NOT */ 23715 | 4 23716 /* SelectorFlags.ELEMENT */ 23717 , selector.element, ...selector.attrs, ...classes]; 23718 } else if (selector.attrs.length) { 23719 return [1 23720 /* SelectorFlags.NOT */ 23721 | 2 23722 /* SelectorFlags.ATTRIBUTE */ 23723 , ...selector.attrs, ...classes]; 23724 } else { 23725 return selector.classNames && selector.classNames.length ? [1 23726 /* SelectorFlags.NOT */ 23727 | 8 23728 /* SelectorFlags.CLASS */ 23729 , ...selector.classNames] : []; 23730 } 23731} 23732 23733function parserSelectorToR3Selector(selector) { 23734 const positive = parserSelectorToSimpleSelector(selector); 23735 const negative = selector.notSelectors && selector.notSelectors.length ? selector.notSelectors.map(notSelector => parserSelectorToNegativeSelector(notSelector)) : []; 23736 return positive.concat(...negative); 23737} 23738 23739function parseSelectorToR3Selector(selector) { 23740 return selector ? CssSelector.parse(selector).map(parserSelectorToR3Selector) : []; 23741} 23742 23743var core = /*#__PURE__*/Object.freeze({ 23744 __proto__: null, 23745 emitDistinctChangesOnlyDefaultValue: emitDistinctChangesOnlyDefaultValue, 23746 23747 get ViewEncapsulation() { 23748 return ViewEncapsulation; 23749 }, 23750 23751 get ChangeDetectionStrategy() { 23752 return ChangeDetectionStrategy; 23753 }, 23754 23755 CUSTOM_ELEMENTS_SCHEMA: CUSTOM_ELEMENTS_SCHEMA,
23756 NO_ERRORS_SCHEMA: NO_ERRORS_SCHEMA, 23757 Type: Type$1, 23758 23759 get SecurityContext() { 23760 return SecurityContext; 23761 }, 23762 23763 get MissingTranslationStrategy() { 23764 return MissingTranslationStrategy; 23765 }, 23766 23767 parseSelectorToR3Selector: parseSelectorToR3Selector 23768}); 23769/** 23770 * @license 23771 * Copyright Google LLC All Rights Reserved. 23772 * 23773 * Use of this source code is governed by an MIT-style license that can be 23774 * found in the LICENSE file at https://angular.io/license 23775 */ 23776 23777const DASH_CASE_REGEXP = /-+([a-z0-9])/g; 23778 23779function dashCaseToCamelCase(input) { 23780 return input.replace(DASH_CASE_REGEXP, (...m) => m[1].toUpperCase()); 23781} 23782 23783function splitAtColon(input, defaultValues) { 23784 return _splitAt(input, ':', defaultValues); 23785} 23786 23787function splitAtPeriod(input, defaultValues) { 23788 return _splitAt(input, '.', defaultValues); 23789} 23790 23791function _splitAt(input, character, defaultValues) { 23792 const characterIndex = input.indexOf(character); 23793 if (characterIndex == -1) return defaultValues; 23794 return [input.slice(0, characterIndex).trim(), input.slice(characterIndex + 1).trim()]; 23795} 23796 23797function noUndefined(val) { 23798 return val === undefined ? null : val; 23799} 23800 23801function error(msg) { 23802 throw new Error(`Internal Error: ${msg}`); 23803} // Escape characters that have a special meaning in Regular Expressions 23804 23805 23806function escapeRegExp(s) { 23807 return s.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); 23808} 23809 23810function utf8Encode(str) { 23811 let encoded = []; 23812 23813 for (let index = 0; index < str.length; index++) {
23814 let codePoint = str.charCodeAt(index); // decode surrogate 23815 // see https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae 23816 23817 if (codePoint >= 0xd800 && codePoint <= 0xdbff && str.length > index + 1) { 23818 const low = str.charCodeAt(index + 1); 23819 23820 if (low >= 0xdc00 && low <= 0xdfff) { 23821 index++; 23822 codePoint = (codePoint - 0xd800 << 10) + low - 0xdc00 + 0x10000; 23823 } 23824 } 23825 23826 if (codePoint <= 0x7f) { 23827 encoded.push(codePoint); 23828 } else if (codePoint <= 0x7ff) { 23829 encoded.push(codePoint >> 6 & 0x1F | 0xc0, codePoint & 0x3f | 0x80); 23830 } else if (codePoint <= 0xffff) { 23831 encoded.push(codePoint >> 12 | 0xe0, codePoint >> 6 & 0x3f | 0x80, codePoint & 0x3f | 0x80); 23832 } else if (codePoint <= 0x1fffff) { 23833 encoded.push(codePoint >> 18 & 0x07 | 0xf0, codePoint >> 12 & 0x3f | 0x80, codePoint >> 6 & 0x3f | 0x80, codePoint & 0x3f | 0x80); 23834 } 23835 } 23836 23837 return encoded; 23838} 23839 23840function stringify(token) { 23841 if (typeof token === 'string') { 23842 return token; 23843 } 23844 23845 if (Array.isArray(token)) { 23846 return '[' + token.map(stringify).join(', ') + ']'; 23847 } 23848 23849 if (token == null) { 23850 return '' + token; 23851 } 23852 23853 if (token.overriddenName) { 23854 return `${token.overriddenName}`; 23855 } 23856 23857 if (token.name) { 23858 return `${token.name}`; 23859 } 23860 23861 if (!token.toString) { 23862 return 'object'; 23863 } // WARNING: do not try to `JSON.stringify(token)` here 23864 // see https://github.com/angular/angular/issues/23440 23865 23866 23867 const res = token.toString(); 23868 23869 if (res == null) { 23870 return '' + res; 23871 } 23872 23873 const newLineIndex = res.indexOf('\n'); 23874 return newLineIndex === -1 ? res : res.substring(0, newLineIndex); 23875} 23876 23877class Version { 23878 constructor(full) { 23879 this.full = full; 23880 const splits = full.split('.'); 23881 this.major = splits[0]; 23882 this.minor = splits[1]; 23883 this.patch = splits.slice(2).join('.'); 23884 } 23885 23886} // Check `global` first, because in Node tests both `global` and `window` may be defined and our 23887// `_global` variable should point to the NodeJS `global` in that case. Note: Typeof/Instanceof 23888// checks are considered side-effects in Terser. We explicitly mark this as side-effect free: 23889// https://github.com/terser/terser/issues/250. 23890 23891 23892const _global = /* @__PURE__ */(() => typeof global !== 'undefined' && global || typeof window !== 'undefined' && window || typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope && self)(); 23893 23894function newArray(size, value) { 23895 const list = []; 23896 23897 for (let i = 0; i < size; i++) { 23898 list.push(value); 23899 } 23900 23901 return list; 23902} 23903/** 23904 * Partitions a given array into 2 arrays, based on a boolean value returned by the condition 23905 * function. 23906 * 23907 * @param arr Input array that should be partitioned 23908 * @param conditionFn Condition function that is called for each item in a given array and returns a 23909 * boolean value. 23910 */ 23911 23912 23913function partitionArray(arr, conditionFn) { 23914 const truthy = []; 23915 const falsy = []; 23916 23917 for (const item of arr) { 23918 (conditionFn(item) ? truthy : falsy).push(item); 23919 } 23920 23921 return [truthy, falsy]; 23922} 23923/** 23924 * @license 23925 * Copyright Google LLC All Rights Reserved. 23926 * 23927 * Use of this source code is governed by an MIT-style license that can be 23928 * found in the LICENSE file at https://angular.io/license 23929 */ 23930 23931/** 23932 * Represents a big integer using a buffer of its individual digits, with the least significant 23933 * digit stored at the beginning of the array (little endian). 23934 * 23935 * For performance reasons, each instance is mutable. The addition operation can be done in-place 23936 * to reduce memory pressure of allocation for the digits array. 23937 */ 23938 23939 23940class BigInteger { 23941 /** 23942 * Creates a big integer using its individual digits in little endian storage. 23943 */ 23944 constructor(digits) { 23945 this.digits = digits; 23946 } 23947 23948 static zero() { 23949 return new BigInteger([0]); 23950 } 23951 23952 static one() { 23953 return new BigInteger([1]); 23954 } 23955 /** 23956 * Creates a clone of this instance. 23957 */ 23958 23959 23960 clone() { 23961 return new BigInteger(this.digits.slice()); 23962 } 23963 /** 23964 * Returns a new big integer with the sum of `this` and `other` as its value. This does not mutate 23965 * `this` but instead returns a new instance, unlike `addToSelf`. 23966 */ 23967 23968 23969 add(other) { 23970 const result = this.clone(); 23971 result.addToSelf(other); 23972 return result; 23973 } 23974 /** 23975 * Adds `other` to the instance itself, thereby mutating its value. 23976 */ 23977 23978 23979 addToSelf(other) { 23980 const maxNrOfDigits = Math.max(this.digits.length, other.digits.length);
23981 let carry = 0; 23982 23983 for (let i = 0; i < maxNrOfDigits; i++) { 23984 let digitSum = carry; 23985 23986 if (i < this.digits.length) { 23987 digitSum += this.digits[i]; 23988 } 23989 23990 if (i < other.digits.length) { 23991 digitSum += other.digits[i]; 23992 } 23993 23994 if (digitSum >= 10) { 23995 this.digits[i] = digitSum - 10; 23996 carry = 1; 23997 } else { 23998 this.digits[i] = digitSum; 23999 carry = 0; 24000 } 24001 } // Apply a remaining carry if needed. 24002 24003 24004 if (carry > 0) { 24005 this.digits[maxNrOfDigits] = 1; 24006 } 24007 } 24008 /** 24009 * Builds the decimal string representation of the big integer. As this is stored in 24010 * little endian, the digits are concatenated in reverse order. 24011 */ 24012 24013 24014 toString() { 24015 let res = ''; 24016 24017 for (let i = this.digits.length - 1; i >= 0; i--) { 24018 res += this.digits[i]; 24019 } 24020 24021 return res; 24022 } 24023 24024} 24025/** 24026 * Represents a big integer which is optimized for multiplication operations, as its power-of-twos 24027 * are memoized. See `multiplyBy()` for details on the multiplication algorithm. 24028 */ 24029 24030 24031class BigIntForMultiplication { 24032 constructor(value) { 24033 this.powerOfTwos = [value]; 24034 } 24035 /** 24036 * Returns the big integer itself. 24037 */ 24038 24039 24040 getValue() { 24041 return this.powerOfTwos[0]; 24042 } 24043 /** 24044 * Computes the value for `num * b`, where `num` is a JS number and `b` is a big integer. The 24045 * value for `b` is represented by a storage model that is optimized for this computation. 24046 * 24047 * This operation is implemented in N(log2(num)) by continuous halving of the number, where the 24048 * least-significant bit (LSB) is tested in each iteration. If the bit is set, the bit's index is 24049 * used as exponent into the power-of-two multiplication of `b`. 24050 * 24051 * As an example, consider the multiplication num=42, b=1337. In binary 42 is 0b00101010 and the 24052 * algorithm unrolls into the following iterations: 24053 * 24054 * Iteration | num | LSB | b * 2^iter | Add? | product 24055 * -----------|------------|------|------------|------|-------- 24056 * 0 | 0b00101010 | 0 | 1337 | No | 0 24057 * 1 | 0b00010101 | 1 | 2674 | Yes | 2674 24058 * 2 | 0b00001010 | 0 | 5348 | No | 2674 24059 * 3 | 0b00000101 | 1 | 10696 | Yes | 13370 24060 * 4 | 0b00000010 | 0 | 21392 | No | 13370 24061 * 5 | 0b00000001 | 1 | 42784 | Yes | 56154 24062 * 6 | 0b00000000 | 0 | 85568 | No | 56154 24063 * 24064 * The computed product of 56154 is indeed the correct result. 24065 * 24066 * The `BigIntForMultiplication` representation for a big integer provides memoized access to the 24067 * power-of-two values to reduce the workload in computing those values. 24068 */ 24069 24070 24071 multiplyBy(num) { 24072 const product = BigInteger.zero(); 24073 this.multiplyByAndAddTo(num, product); 24074 return product; 24075 } 24076 /** 24077 * See `multiplyBy()` for details. This function allows for the computed product to be added 24078 * directly to the provided result big integer. 24079 */ 24080 24081 24082 multiplyByAndAddTo(num, result) { 24083 for (let exponent = 0; num !== 0; num = num >>> 1, exponent++) { 24084 if (num & 1) { 24085 const value = this.getMultipliedByPowerOfTwo(exponent); 24086 result.addToSelf(value); 24087 } 24088 } 24089 } 24090 /** 24091 * Computes and memoizes the big integer value for `this.number * 2^exponent`. 24092 */ 24093 24094 24095 getMultipliedByPowerOfTwo(exponent) { 24096 // Compute the powers up until the requested exponent, where each value is computed from its 24097 // predecessor. This is simple as `this.number * 2^(exponent - 1)` only has to be doubled (i.e. 24098 // added to itself) to reach `this.number * 2^exponent`. 24099 for (let i = this.powerOfTwos.length; i <= exponent; i++) { 24100 const previousPower = this.powerOfTwos[i - 1]; 24101 this.powerOfTwos[i] = previousPower.add(previousPower); 24102 } 24103 24104 return this.powerOfTwos[exponent]; 24105 } 24106 24107} 24108/** 24109 * Represents an exponentiation operation for the provided base, of which exponents are computed and 24110 * memoized. The results are represented by a `BigIntForMultiplication` which is tailored for 24111 * multiplication operations by memoizing the power-of-twos. This effectively results in a matrix 24112 * representation that is lazily computed upon request. 24113 */ 24114 24115 24116class BigIntExponentiation { 24117 constructor(base) { 24118 this.base = base; 24119 this.exponents = [new BigIntForMultiplication(BigInteger.one())]; 24120 } 24121 /** 24122 * Compute the value for `this.base^exponent`, resulting in a big integer that is optimized for 24123 * further multiplication operations. 24124 */ 24125 24126
24127 toThePowerOf(exponent) { 24128 // Compute the results up until the requested exponent, where every value is computed from its 24129 // predecessor. This is because `this.base^(exponent - 1)` only has to be multiplied by `base` 24130 // to reach `this.base^exponent`. 24131 for (let i = this.exponents.length; i <= exponent; i++) { 24132 const value = this.exponents[i - 1].multiplyBy(this.base); 24133 this.exponents[i] = new BigIntForMultiplication(value); 24134 } 24135 24136 return this.exponents[exponent]; 24137 } 24138 24139} 24140/** 24141 * @license 24142 * Copyright Google LLC All Rights Reserved. 24143 * 24144 * Use of this source code is governed by an MIT-style license that can be 24145 * found in the LICENSE file at https://angular.io/license 24146 */ 24147 24148/** 24149 * Return the message id or compute it using the XLIFF1 digest. 24150 */ 24151 24152 24153function digest$1(message) { 24154 return message.id || computeDigest(message); 24155} 24156/** 24157 * Compute the message id using the XLIFF1 digest. 24158 */ 24159 24160 24161function computeDigest(message) { 24162 return sha1(serializeNodes(message.nodes).join('') + `[${message.meaning}]`); 24163} 24164/** 24165 * Return the message id or compute it using the XLIFF2/XMB/$localize digest. 24166 */ 24167 24168 24169function decimalDigest(message) { 24170 return message.id || computeDecimalDigest(message); 24171} 24172/** 24173 * Compute the message id using the XLIFF2/XMB/$localize digest. 24174 */ 24175 24176 24177function computeDecimalDigest(message) { 24178 const visitor = new _SerializerIgnoreIcuExpVisitor(); 24179 const parts = message.nodes.map(a => a.visit(visitor, null)); 24180 return computeMsgId(parts.join(''), message.meaning); 24181} 24182/** 24183 * Serialize the i18n ast to something xml-like in order to generate an UID. 24184 * 24185 * The visitor is also used in the i18n parser tests 24186 * 24187 * @internal 24188 */ 24189 24190 24191class _SerializerVisitor { 24192 visitText(text, context) { 24193 return text.value; 24194 } 24195 24196 visitContainer(container, context) { 24197 return `[${container.children.map(child => child.visit(this)).join(', ')}]`; 24198 } 24199 24200 visitIcu(icu, context) { 24201 const strCases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`); 24202 return `{${icu.expression}, ${icu.type}, ${strCases.join(', ')}}`; 24203 } 24204 24205 visitTagPlaceholder(ph, context) { 24206 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}">`; 24207 } 24208 24209 visitPlaceholder(ph, context) { 24210 return ph.value ? `<ph name="${ph.name}">${ph.value}</ph>` : `<ph name="${ph.name}"/>`; 24211 } 24212 24213 visitIcuPlaceholder(ph, context) { 24214 return `<ph icu name="${ph.name}">${ph.value.visit(this)}</ph>`; 24215 } 24216 24217} 24218 24219const serializerVisitor$1 = new _SerializerVisitor(); 24220 24221function serializeNodes(nodes) { 24222 return nodes.map(a => a.visit(serializerVisitor$1, null)); 24223} 24224/** 24225 * Serialize the i18n ast to something xml-like in order to generate an UID. 24226 * 24227 * Ignore the ICU expressions so that message IDs stays identical if only the expression changes. 24228 * 24229 * @internal 24230 */ 24231 24232 24233class _SerializerIgnoreIcuExpVisitor extends _SerializerVisitor { 24234 visitIcu(icu, context) { 24235 let strCases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`); // Do not take the expression into account 24236 24237 return `{${icu.type}, ${strCases.join(', ')}}`; 24238 } 24239 24240} 24241/** 24242 * Compute the SHA1 of the given string 24243 * 24244 * see https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf 24245 * 24246 * WARNING: this function has not been designed not tested with security in mind. 24247 * DO NOT USE IT IN A SECURITY SENSITIVE CONTEXT. 24248 */ 24249 24250 24251function sha1(str) { 24252 const utf8 = utf8Encode(str); 24253 const words32 = bytesToWords32(utf8, Endian.Big); 24254 const len = utf8.length * 8; 24255 const w = newArray(80); 24256 let a = 0x67452301, 24257 b = 0xefcdab89, 24258 c = 0x98badcfe, 24259 d = 0x10325476, 24260 e = 0xc3d2e1f0; 24261 words32[len >> 5] |= 0x80 << 24 - len % 32; 24262 words32[(len + 64 >> 9 << 4) + 15] = len; 24263 24264 for (let i = 0; i < words32.length; i += 16) { 24265 const h0 = a, 24266 h1 = b, 24267 h2 = c, 24268 h3 = d, 24269 h4 = e; 24270 24271 for (let j = 0; j < 80; j++) { 24272 if (j < 16) { 24273 w[j] = words32[i + j]; 24274 } else { 24275 w[j] = rol32(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1); 24276 } 24277 24278 const fkVal = fk(j, b, c, d); 24279 const f = fkVal[0];
24280 const k = fkVal[1]; 24281 const temp = [rol32(a, 5), f, e, k, w[j]].reduce(add32); 24282 e = d; 24283 d = c; 24284 c = rol32(b, 30); 24285 b = a; 24286 a = temp; 24287 } 24288 24289 a = add32(a, h0); 24290 b = add32(b, h1); 24291 c = add32(c, h2); 24292 d = add32(d, h3); 24293 e = add32(e, h4); 24294 } 24295 24296 return bytesToHexString(words32ToByteString([a, b, c, d, e])); 24297} 24298 24299function fk(index, b, c, d) { 24300 if (index < 20) { 24301 return [b & c | ~b & d, 0x5a827999]; 24302 } 24303 24304 if (index < 40) { 24305 return [b ^ c ^ d, 0x6ed9eba1]; 24306 } 24307 24308 if (index < 60) { 24309 return [b & c | b & d | c & d, 0x8f1bbcdc]; 24310 } 24311 24312 return [b ^ c ^ d, 0xca62c1d6]; 24313} 24314/** 24315 * Compute the fingerprint of the given string 24316 * 24317 * The output is 64 bit number encoded as a decimal string 24318 * 24319 * based on: 24320 * https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/GoogleJsMessageIdGenerator.java 24321 */ 24322 24323 24324function fingerprint(str) { 24325 const utf8 = utf8Encode(str); 24326 let hi = hash32(utf8, 0); 24327 let lo = hash32(utf8, 102072); 24328 24329 if (hi == 0 && (lo == 0 || lo == 1)) { 24330 hi = hi ^ 0x130f9bef; 24331 lo = lo ^ -0x6b5f56d8; 24332 } 24333 24334 return [hi, lo]; 24335} 24336 24337function computeMsgId(msg, meaning = '') { 24338 let msgFingerprint = fingerprint(msg); 24339 24340 if (meaning) { 24341 const meaningFingerprint = fingerprint(meaning); 24342 msgFingerprint = add64(rol64(msgFingerprint, 1), meaningFingerprint); 24343 } 24344 24345 const hi = msgFingerprint[0]; 24346 const lo = msgFingerprint[1]; 24347 return wordsToDecimalString(hi & 0x7fffffff, lo); 24348} 24349 24350function hash32(bytes, c) { 24351 let a = 0x9e3779b9, 24352 b = 0x9e3779b9; 24353 let i; 24354 const len = bytes.length; 24355 24356 for (i = 0; i + 12 <= len; i += 12) { 24357 a = add32(a, wordAt(bytes, i, Endian.Little)); 24358 b = add32(b, wordAt(bytes, i + 4, Endian.Little)); 24359 c = add32(c, wordAt(bytes, i + 8, Endian.Little)); 24360 const res = mix(a, b, c); 24361 a = res[0], b = res[1], c = res[2]; 24362 } 24363 24364 a = add32(a, wordAt(bytes, i, Endian.Little)); 24365 b = add32(b, wordAt(bytes, i + 4, Endian.Little)); // the first byte of c is reserved for the length 24366 24367 c = add32(c, len); 24368 c = add32(c, wordAt(bytes, i + 8, Endian.Little) << 8); 24369 return mix(a, b, c)[2]; 24370} // clang-format off 24371 24372 24373function mix(a, b, c) { 24374 a = sub32(a, b); 24375 a = sub32(a, c); 24376 a ^= c >>> 13; 24377 b = sub32(b, c); 24378 b = sub32(b, a); 24379 b ^= a << 8; 24380 c = sub32(c, a); 24381 c = sub32(c, b); 24382 c ^= b >>> 13; 24383 a = sub32(a, b); 24384 a = sub32(a, c); 24385 a ^= c >>> 12; 24386 b = sub32(b, c); 24387 b = sub32(b, a); 24388 b ^= a << 16; 24389 c = sub32(c, a); 24390 c = sub32(c, b); 24391 c ^= b >>> 5; 24392 a = sub32(a, b); 24393 a = sub32(a, c); 24394 a ^= c >>> 3; 24395 b = sub32(b, c); 24396 b = sub32(b, a); 24397 b ^= a << 10; 24398 c = sub32(c, a); 24399 c = sub32(c, b); 24400 c ^= b >>> 15; 24401 return [a, b, c]; 24402} // clang-format on 24403// Utils 24404 24405 24406var Endian; 24407 24408(function (Endian) { 24409 Endian[Endian["Little"] = 0] = "Little"; 24410 Endian[Endian["Big"] = 1] = "Big"; 24411})(Endian || (Endian = {})); 24412 24413function add32(a, b) { 24414 return add32to64(a, b)[1]; 24415} 24416 24417function add32to64(a, b) { 24418 const low = (a & 0xffff) + (b & 0xffff); 24419 const high = (a >>> 16) + (b >>> 16) + (low >>> 16); 24420 return [high >>> 16, high << 16 | low & 0xffff]; 24421} 24422 24423function add64(a, b) { 24424 const ah = a[0], 24425 al = a[1]; 24426 const bh = b[0], 24427 bl = b[1]; 24428 const result = add32to64(al, bl); 24429 const carry = result[0]; 24430 const l = result[1]; 24431 const h = add32(add32(ah, bh), carry); 24432 return [h, l]; 24433} 24434 24435function sub32(a, b) { 24436 const low = (a & 0xffff) - (b & 0xffff); 24437 const high = (a >> 16) - (b >> 16) + (low >> 16); 24438 return high << 16 | low & 0xffff; 24439} // Rotate a 32b number left `count` position 24440 24441 24442function rol32(a, count) { 24443 return a << count | a >>> 32 - count; 24444} // Rotate a 64b number left `count` position 24445 24446 24447function rol64(num, count) { 24448 const hi = num[0], 24449 lo = num[1]; 24450 const h = hi << count | lo >>> 32 - count; 24451 const l = lo << count | hi >>> 32 - count; 24452 return [h, l]; 24453} 24454 24455function bytesToWords32(bytes, endian) { 24456 const size = bytes.length + 3 >>> 2; 24457 const words32 = []; 24458 24459 for (let i = 0; i < size; i++) { 24460 words32[i] = wordAt(bytes, i * 4, endian); 24461 } 24462 24463 return words32; 24464} 24465 24466function byteAt(bytes, index) { 24467 return index >= bytes.length ? 0 : bytes[index]; 24468} 24469 24470function wordAt(bytes, index, endian) { 24471 let word = 0; 24472 24473 if (endian === Endian.Big) { 24474 for (let i = 0; i < 4; i++) {
24475 word += byteAt(bytes, index + i) << 24 - 8 * i; 24476 } 24477 } else { 24478 for (let i = 0; i < 4; i++) { 24479 word += byteAt(bytes, index + i) << 8 * i; 24480 } 24481 } 24482 24483 return word; 24484} 24485 24486function words32ToByteString(words32) { 24487 return words32.reduce((bytes, word) => bytes.concat(word32ToByteString(word)), []); 24488} 24489 24490function word32ToByteString(word) { 24491 let bytes = []; 24492 24493 for (let i = 0; i < 4; i++) { 24494 bytes.push(word >>> 8 * (3 - i) & 0xff); 24495 } 24496 24497 return bytes; 24498} 24499 24500function bytesToHexString(bytes) { 24501 let hex = ''; 24502 24503 for (let i = 0; i < bytes.length; i++) { 24504 const b = byteAt(bytes, i); 24505 hex += (b >>> 4).toString(16) + (b & 0x0f).toString(16); 24506 } 24507 24508 return hex.toLowerCase(); 24509} 24510/** 24511 * Create a shared exponentiation pool for base-256 computations. This shared pool provides memoized 24512 * power-of-256 results with memoized power-of-two computations for efficient multiplication. 24513 * 24514 * For our purposes, this can be safely stored as a global without memory concerns. The reason is 24515 * that we encode two words, so only need the 0th (for the low word) and 4th (for the high word) 24516 * exponent. 24517 */ 24518 24519 24520const base256 = new BigIntExponentiation(256); 24521/** 24522 * Represents two 32-bit words as a single decimal number. This requires a big integer storage 24523 * model as JS numbers are not accurate enough to represent the 64-bit number. 24524 * 24525 * Based on https://www.danvk.org/hex2dec.html 24526 */ 24527 24528function wordsToDecimalString(hi, lo) { 24529 // Encode the four bytes in lo in the lower digits of the decimal number. 24530 // Note: the multiplication results in lo itself but represented by a big integer using its 24531 // decimal digits. 24532 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 24533 // this multiplication factor is applied. 24534 24535 base256.toThePowerOf(4).multiplyByAndAddTo(hi, decimal); 24536 return decimal.toString(); 24537} 24538/** 24539 * @license 24540 * Copyright Google LLC All Rights Reserved. 24541 * 24542 * Use of this source code is governed by an MIT-style license that can be 24543 * found in the LICENSE file at https://angular.io/license 24544 */ 24545//// Types 24546 24547 24548var TypeModifier; 24549 24550(function (TypeModifier) { 24551 TypeModifier[TypeModifier["None"] = 0] = "None"; 24552 TypeModifier[TypeModifier["Const"] = 1] = "Const"; 24553})(TypeModifier || (TypeModifier = {})); 24554 24555class Type { 24556 constructor(modifiers = TypeModifier.None) { 24557 this.modifiers = modifiers; 24558 } 24559 24560 hasModifier(modifier) { 24561 return (this.modifiers & modifier) !== 0; 24562 } 24563 24564} 24565 24566var BuiltinTypeName; 24567 24568(function (BuiltinTypeName) { 24569 BuiltinTypeName[BuiltinTypeName["Dynamic"] = 0] = "Dynamic"; 24570 BuiltinTypeName[BuiltinTypeName["Bool"] = 1] = "Bool"; 24571 BuiltinTypeName[BuiltinTypeName["String"] = 2] = "String"; 24572 BuiltinTypeName[BuiltinTypeName["Int"] = 3] = "Int"; 24573 BuiltinTypeName[BuiltinTypeName["Number"] = 4] = "Number"; 24574 BuiltinTypeName[BuiltinTypeName["Function"] = 5] = "Function"; 24575 BuiltinTypeName[BuiltinTypeName["Inferred"] = 6] = "Inferred"; 24576 BuiltinTypeName[BuiltinTypeName["None"] = 7] = "None"; 24577})(BuiltinTypeName || (BuiltinTypeName = {})); 24578 24579class BuiltinType extends Type { 24580 constructor(name, modifiers) { 24581 super(modifiers); 24582 this.name = name; 24583 } 24584 24585 visitType(visitor, context) { 24586 return visitor.visitBuiltinType(this, context); 24587 } 24588 24589} 24590 24591class ExpressionType extends Type { 24592 constructor(value, modifiers, typeParams = null) { 24593 super(modifiers); 24594 this.value = value; 24595 this.typeParams = typeParams; 24596 } 24597 24598 visitType(visitor, context) { 24599 return visitor.visitExpressionType(this, context); 24600 } 24601 24602} 24603 24604class ArrayType extends Type { 24605 constructor(of, modifiers) { 24606 super(modifiers); 24607 this.of = of; 24608 } 24609 24610 visitType(visitor, context) { 24611 return visitor.visitArrayType(this, context); 24612 } 24613 24614} 24615 24616class MapType extends Type { 24617 constructor(valueType, modifiers) { 24618 super(modifiers); 24619 this.valueType = valueType || null; 24620 } 24621 24622 visitType(visitor, context) { 24623 return visitor.visitMapType(this, context); 24624 } 24625 24626} 24627 24628const DYNAMIC_TYPE = new BuiltinType(BuiltinTypeName.Dynamic); 24629const INFERRED_TYPE = new BuiltinType(BuiltinTypeName.Inferred); 24630const BOOL_TYPE = new BuiltinType(BuiltinTypeName.Bool); 24631const INT_TYPE = new BuiltinType(BuiltinTypeName.Int); 24632const NUMBER_TYPE = new BuiltinType(BuiltinTypeName.Number); 24633const STRING_TYPE = new BuiltinType(BuiltinTypeName.String); 24634const FUNCTION_TYPE = new BuiltinType(BuiltinTypeName.Function); 24635const NONE_TYPE = new BuiltinType(BuiltinTypeName.None); ///// Expressions 24636 24637var UnaryOperator; 24638 24639(function (UnaryOperator) { 24640 UnaryOperator[UnaryOperator["Minus"] = 0] = "Minus"; 24641 UnaryOperator[UnaryOperator["Plus"] = 1] = "Plus"; 24642})(UnaryOperator || (UnaryOperator = {})); 24643 24644var BinaryOperator; 24645 24646(function (BinaryOperator) { 24647 BinaryOperator[BinaryOperator["Equals"] = 0] = "Equals"; 24648 BinaryOperator[BinaryOperator["NotEquals"] = 1] = "NotEquals"; 24649 BinaryOperator[BinaryOperator["Identical"] = 2] = "Identical"; 24650 BinaryOperator[BinaryOperator["NotIdentical"] = 3] = "NotIdentical"; 24651 BinaryOperator[BinaryOperator["Minus"] = 4] = "Minus"; 24652 BinaryOperator[BinaryOperator["Plus"] = 5] = "Plus"; 24653 BinaryOperator[BinaryOperator["Divide"] = 6] = "Divide"; 24654 BinaryOperator[BinaryOperator["Multiply"] = 7] = "Multiply"; 24655 BinaryOperator[BinaryOperator["Modulo"] = 8] = "Modulo"; 24656 BinaryOperator[BinaryOperator["And"] = 9] = "And"; 24657 BinaryOperator[BinaryOperator["Or"] = 10] = "Or"; 24658 BinaryOperator[BinaryOperator["BitwiseAnd"] = 11] = "BitwiseAnd"; 24659 BinaryOperator[BinaryOperator["Lower"] = 12] = "Lower"; 24660 BinaryOperator[BinaryOperator["LowerEquals"] = 13] = "LowerEquals"; 24661 BinaryOperator[BinaryOperator["Bigger"] = 14] = "Bigger"; 24662 BinaryOperator[BinaryOperator["BiggerEquals"] = 15] = "BiggerEquals"; 24663 BinaryOperator[BinaryOperator["NullishCoalesce"] = 16] = "NullishCoalesce"; 24664})(BinaryOperator || (BinaryOperator = {})); 24665 24666function nullSafeIsEquivalent(base, other) { 24667 if (base == null || other == null) { 24668 return base == other; 24669 } 24670 24671 return base.isEquivalent(other); 24672} 24673 24674function areAllEquivalentPredicate(base, other, equivalentPredicate) { 24675 const len = base.length; 24676 24677 if (len !== other.length) { 24678 return false;
24679 } 24680 24681 for (let i = 0; i < len; i++) { 24682 if (!equivalentPredicate(base[i], other[i])) { 24683 return false; 24684 } 24685 } 24686 24687 return true; 24688} 24689 24690function areAllEquivalent(base, other) { 24691 return areAllEquivalentPredicate(base, other, (baseElement, otherElement) => baseElement.isEquivalent(otherElement)); 24692} 24693 24694class Expression { 24695 constructor(type, sourceSpan) { 24696 this.type = type || null; 24697 this.sourceSpan = sourceSpan || null; 24698 } 24699 24700 prop(name, sourceSpan) { 24701 return new ReadPropExpr(this, name, null, sourceSpan); 24702 } 24703 24704 key(index, type, sourceSpan) { 24705 return new ReadKeyExpr(this, index, type, sourceSpan); 24706 } 24707 24708 callFn(params, sourceSpan, pure) { 24709 return new InvokeFunctionExpr(this, params, null, sourceSpan, pure); 24710 } 24711 24712 instantiate(params, type, sourceSpan) { 24713 return new InstantiateExpr(this, params, type, sourceSpan); 24714 } 24715 24716 conditional(trueCase, falseCase = null, sourceSpan) { 24717 return new ConditionalExpr(this, trueCase, falseCase, null, sourceSpan); 24718 } 24719 24720 equals(rhs, sourceSpan) { 24721 return new BinaryOperatorExpr(BinaryOperator.Equals, this, rhs, null, sourceSpan); 24722 } 24723 24724 notEquals(rhs, sourceSpan) { 24725 return new BinaryOperatorExpr(BinaryOperator.NotEquals, this, rhs, null, sourceSpan); 24726 } 24727 24728 identical(rhs, sourceSpan) { 24729 return new BinaryOperatorExpr(BinaryOperator.Identical, this, rhs, null, sourceSpan); 24730 } 24731 24732 notIdentical(rhs, sourceSpan) { 24733 return new BinaryOperatorExpr(BinaryOperator.NotIdentical, this, rhs, null, sourceSpan); 24734 } 24735 24736 minus(rhs, sourceSpan) { 24737 return new BinaryOperatorExpr(BinaryOperator.Minus, this, rhs, null, sourceSpan); 24738 } 24739 24740 plus(rhs, sourceSpan) { 24741 return new BinaryOperatorExpr(BinaryOperator.Plus, this, rhs, null, sourceSpan); 24742 } 24743 24744 divide(rhs, sourceSpan) { 24745 return new BinaryOperatorExpr(BinaryOperator.Divide, this, rhs, null, sourceSpan); 24746 } 24747 24748 multiply(rhs, sourceSpan) { 24749 return new BinaryOperatorExpr(BinaryOperator.Multiply, this, rhs, null, sourceSpan); 24750 } 24751 24752 modulo(rhs, sourceSpan) { 24753 return new BinaryOperatorExpr(BinaryOperator.Modulo, this, rhs, null, sourceSpan); 24754 } 24755 24756 and(rhs, sourceSpan) { 24757 return new BinaryOperatorExpr(BinaryOperator.And, this, rhs, null, sourceSpan); 24758 } 24759 24760 bitwiseAnd(rhs, sourceSpan, parens = true) { 24761 return new BinaryOperatorExpr(BinaryOperator.BitwiseAnd, this, rhs, null, sourceSpan, parens); 24762 } 24763 24764 or(rhs, sourceSpan) { 24765 return new BinaryOperatorExpr(BinaryOperator.Or, this, rhs, null, sourceSpan); 24766 } 24767 24768 lower(rhs, sourceSpan) { 24769 return new BinaryOperatorExpr(BinaryOperator.Lower, this, rhs, null, sourceSpan); 24770 } 24771 24772 lowerEquals(rhs, sourceSpan) { 24773 return new BinaryOperatorExpr(BinaryOperator.LowerEquals, this, rhs, null, sourceSpan); 24774 } 24775 24776 bigger(rhs, sourceSpan) { 24777 return new BinaryOperatorExpr(BinaryOperator.Bigger, this, rhs, null, sourceSpan); 24778 } 24779 24780 biggerEquals(rhs, sourceSpan) { 24781 return new BinaryOperatorExpr(BinaryOperator.BiggerEquals, this, rhs, null, sourceSpan); 24782 } 24783 24784 isBlank(sourceSpan) { 24785 // Note: We use equals by purpose here to compare to null and undefined in JS. 24786 // We use the typed null to allow strictNullChecks to narrow types. 24787 return this.equals(TYPED_NULL_EXPR, sourceSpan); 24788 } 24789 24790 nullishCoalesce(rhs, sourceSpan) { 24791 return new BinaryOperatorExpr(BinaryOperator.NullishCoalesce, this, rhs, null, sourceSpan); 24792 } 24793 24794 toStmt() { 24795 return new ExpressionStatement(this, null); 24796 } 24797 24798} 24799 24800class ReadVarExpr extends Expression { 24801 constructor(name, type, sourceSpan) { 24802 super(type, sourceSpan); 24803 this.name = name; 24804 } 24805 24806 isEquivalent(e) { 24807 return e instanceof ReadVarExpr && this.name === e.name; 24808 } 24809 24810 isConstant() { 24811 return false; 24812 } 24813 24814 visitExpression(visitor, context) { 24815 return visitor.visitReadVarExpr(this, context); 24816 } 24817 24818 set(value) { 24819 return new WriteVarExpr(this.name, value, null, this.sourceSpan); 24820 } 24821 24822} 24823 24824class TypeofExpr extends Expression { 24825 constructor(expr, type, sourceSpan) { 24826 super(type, sourceSpan); 24827 this.expr = expr; 24828 } 24829 24830 visitExpression(visitor, context) { 24831 return visitor.visitTypeofExpr(this, context); 24832 } 24833 24834 isEquivalent(e) { 24835 return e instanceof TypeofExpr && e.expr.isEquivalent(this.expr); 24836 } 24837 24838 isConstant() { 24839 return this.expr.isConstant(); 24840 } 24841 24842} 24843
24844class WrappedNodeExpr extends Expression { 24845 constructor(node, type, sourceSpan) { 24846 super(type, sourceSpan); 24847 this.node = node; 24848 } 24849 24850 isEquivalent(e) { 24851 return e instanceof WrappedNodeExpr && this.node === e.node; 24852 } 24853 24854 isConstant() { 24855 return false; 24856 } 24857 24858 visitExpression(visitor, context) { 24859 return visitor.visitWrappedNodeExpr(this, context); 24860 } 24861 24862} 24863 24864class WriteVarExpr extends Expression { 24865 constructor(name, value, type, sourceSpan) { 24866 super(type || value.type, sourceSpan); 24867 this.name = name; 24868 this.value = value; 24869 } 24870 24871 isEquivalent(e) { 24872 return e instanceof WriteVarExpr && this.name === e.name && this.value.isEquivalent(e.value); 24873 } 24874 24875 isConstant() { 24876 return false; 24877 } 24878 24879 visitExpression(visitor, context) { 24880 return visitor.visitWriteVarExpr(this, context); 24881 } 24882 24883 toDeclStmt(type, modifiers) { 24884 return new DeclareVarStmt(this.name, this.value, type, modifiers, this.sourceSpan); 24885 } 24886 24887 toConstDecl() { 24888 return this.toDeclStmt(INFERRED_TYPE, StmtModifier.Final); 24889 } 24890 24891} 24892 24893class WriteKeyExpr extends Expression { 24894 constructor(receiver, index, value, type, sourceSpan) { 24895 super(type || value.type, sourceSpan); 24896 this.receiver = receiver; 24897 this.index = index; 24898 this.value = value; 24899 } 24900 24901 isEquivalent(e) { 24902 return e instanceof WriteKeyExpr && this.receiver.isEquivalent(e.receiver) && this.index.isEquivalent(e.index) && this.value.isEquivalent(e.value); 24903 } 24904 24905 isConstant() { 24906 return false; 24907 } 24908 24909 visitExpression(visitor, context) { 24910 return visitor.visitWriteKeyExpr(this, context); 24911 } 24912 24913} 24914 24915class WritePropExpr extends Expression { 24916 constructor(receiver, name, value, type, sourceSpan) { 24917 super(type || value.type, sourceSpan); 24918 this.receiver = receiver; 24919 this.name = name; 24920 this.value = value; 24921 } 24922 24923 isEquivalent(e) { 24924 return e instanceof WritePropExpr && this.receiver.isEquivalent(e.receiver) && this.name === e.name && this.value.isEquivalent(e.value); 24925 } 24926 24927 isConstant() { 24928 return false; 24929 } 24930 24931 visitExpression(visitor, context) { 24932 return visitor.visitWritePropExpr(this, context); 24933 } 24934 24935} 24936 24937class InvokeFunctionExpr extends Expression { 24938 constructor(fn, args, type, sourceSpan, pure = false) { 24939 super(type, sourceSpan); 24940 this.fn = fn; 24941 this.args = args; 24942 this.pure = pure; 24943 } 24944 24945 isEquivalent(e) { 24946 return e instanceof InvokeFunctionExpr && this.fn.isEquivalent(e.fn) && areAllEquivalent(this.args, e.args) && this.pure === e.pure; 24947 } 24948 24949 isConstant() { 24950 return false; 24951 } 24952 24953 visitExpression(visitor, context) { 24954 return visitor.visitInvokeFunctionExpr(this, context); 24955 } 24956 24957} 24958 24959class TaggedTemplateExpr extends Expression { 24960 constructor(tag, template, type, sourceSpan) { 24961 super(type, sourceSpan); 24962 this.tag = tag; 24963 this.template = template; 24964 } 24965 24966 isEquivalent(e) { 24967 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); 24968 } 24969 24970 isConstant() { 24971 return false; 24972 } 24973 24974 visitExpression(visitor, context) { 24975 return visitor.visitTaggedTemplateExpr(this, context); 24976 } 24977 24978} 24979 24980class InstantiateExpr extends Expression { 24981 constructor(classExpr, args, type, sourceSpan) { 24982 super(type, sourceSpan); 24983 this.classExpr = classExpr; 24984 this.args = args; 24985 } 24986 24987 isEquivalent(e) { 24988 return e instanceof InstantiateExpr && this.classExpr.isEquivalent(e.classExpr) && areAllEquivalent(this.args, e.args); 24989 } 24990 24991 isConstant() { 24992 return false; 24993 } 24994 24995 visitExpression(visitor, context) { 24996 return visitor.visitInstantiateExpr(this, context); 24997 } 24998 24999} 25000 25001class LiteralExpr extends Expression { 25002 constructor(value, type, sourceSpan) { 25003 super(type, sourceSpan); 25004 this.value = value; 25005 } 25006 25007 isEquivalent(e) { 25008 return e instanceof LiteralExpr && this.value === e.value; 25009 } 25010 25011 isConstant() { 25012 return true; 25013 } 25014 25015 visitExpression(visitor, context) { 25016 return visitor.visitLiteralExpr(this, context); 25017 } 25018 25019} 25020 25021class TemplateLiteral { 25022 constructor(elements, expressions) { 25023 this.elements = elements; 25024 this.expressions = expressions; 25025 } 25026 25027} 25028 25029class TemplateLiteralElement { 25030 constructor(text, sourceSpan, rawText) { 25031 this.text = text; 25032 this.sourceSpan = sourceSpan; // If `rawText` is not provided, try to extract the raw string from its 25033 // associated `sourceSpan`. If that is also not available, "fake" the raw 25034 // string instead by escaping the following control sequences: 25035 // - "\" would otherwise indicate that the next character is a control character. 25036 // - "`" and "${" are template string control sequences that would otherwise prematurely 25037 // indicate the end of the template literal element. 25038 25039 this.rawText = rawText ?? sourceSpan?.toString() ?? escapeForTemplateLiteral(escapeSlashes(text)); 25040 } 25041 25042} 25043 25044class LiteralPiece { 25045 constructor(text, sourceSpan) { 25046 this.text = text; 25047 this.sourceSpan = sourceSpan; 25048 } 25049 25050} 25051 25052class PlaceholderPiece { 25053 /** 25054 * Create a new instance of a `PlaceholderPiece`. 25055 * 25056 * @param text the name of this placeholder (e.g. `PH_1`).
25057 * @param sourceSpan the location of this placeholder in its localized message the source code. 25058 * @param associatedMessage reference to another message that this placeholder is associated with. 25059 * The `associatedMessage` is mainly used to provide a relationship to an ICU message that has 25060 * been extracted out from the message containing the placeholder. 25061 */ 25062 constructor(text, sourceSpan, associatedMessage) { 25063 this.text = text; 25064 this.sourceSpan = sourceSpan; 25065 this.associatedMessage = associatedMessage; 25066 } 25067 25068} 25069 25070const MEANING_SEPARATOR$1 = '|'; 25071const ID_SEPARATOR$1 = '@@'; 25072const LEGACY_ID_INDICATOR = 'â'; 25073 25074class LocalizedString extends Expression { 25075 constructor(metaBlock, messageParts, placeHolderNames, expressions, sourceSpan) { 25076 super(STRING_TYPE, sourceSpan); 25077 this.metaBlock = metaBlock; 25078 this.messageParts = messageParts; 25079 this.placeHolderNames = placeHolderNames; 25080 this.expressions = expressions; 25081 } 25082 25083 isEquivalent(e) { 25084 // return e instanceof LocalizedString && this.message === e.message; 25085 return false; 25086 } 25087 25088 isConstant() { 25089 return false; 25090 } 25091 25092 visitExpression(visitor, context) { 25093 return visitor.visitLocalizedString(this, context); 25094 } 25095 /** 25096 * Serialize the given `meta` and `messagePart` into "cooked" and "raw" strings that can be used 25097 * in a `$localize` tagged string. The format of the metadata is the same as that parsed by 25098 * `parseI18nMeta()`. 25099 * 25100 * @param meta The metadata to serialize 25101 * @param messagePart The first part of the tagged string 25102 */ 25103 25104 25105 serializeI18nHead() { 25106 let metaBlock = this.metaBlock.description || ''; 25107 25108 if (this.metaBlock.meaning) { 25109 metaBlock = `${this.metaBlock.meaning}${MEANING_SEPARATOR$1}${metaBlock}`; 25110 } 25111 25112 if (this.metaBlock.customId) { 25113 metaBlock = `${metaBlock}${ID_SEPARATOR$1}${this.metaBlock.customId}`; 25114 } 25115 25116 if (this.metaBlock.legacyIds) { 25117 this.metaBlock.legacyIds.forEach(legacyId => { 25118 metaBlock = `${metaBlock}${LEGACY_ID_INDICATOR}${legacyId}`; 25119 }); 25120 } 25121 25122 return createCookedRawString(metaBlock, this.messageParts[0].text, this.getMessagePartSourceSpan(0)); 25123 } 25124 25125 getMessagePartSourceSpan(i) { 25126 return this.messageParts[i]?.sourceSpan ?? this.sourceSpan; 25127 } 25128 25129 getPlaceholderSourceSpan(i) { 25130 return this.placeHolderNames[i]?.sourceSpan ?? this.expressions[i]?.sourceSpan ?? this.sourceSpan; 25131 } 25132 /** 25133 * Serialize the given `placeholderName` and `messagePart` into "cooked" and "raw" strings that 25134 * can be used in a `$localize` tagged string. 25135 * 25136 * The format is `:<placeholder-name>[@@<associated-id>]:`. 25137 * 25138 * The `associated-id` is the message id of the (usually an ICU) message to which this placeholder 25139 * refers. 25140 * 25141 * @param partIndex The index of the message part to serialize. 25142 */ 25143 25144 25145 serializeI18nTemplatePart(partIndex) { 25146 const placeholder = this.placeHolderNames[partIndex - 1]; 25147 const messagePart = this.messageParts[partIndex]; 25148 let metaBlock = placeholder.text; 25149 25150 if (placeholder.associatedMessage?.legacyIds.length === 0) { 25151 metaBlock += `${ID_SEPARATOR$1}${computeMsgId(placeholder.associatedMessage.messageString, placeholder.associatedMessage.meaning)}`; 25152 } 25153 25154 return createCookedRawString(metaBlock, messagePart.text, this.getMessagePartSourceSpan(partIndex)); 25155 } 25156 25157} 25158 25159const escapeSlashes = str => str.replace(/\\/g, '\\\\'); 25160 25161const escapeStartingColon = str => str.replace(/^:/, '\\:'); 25162 25163const escapeColons = str => str.replace(/:/g, '\\:'); 25164 25165const escapeForTemplateLiteral = str => str.replace(/`/g, '\\`').replace(/\${/g, '$\\{'); 25166/** 25167 * Creates a `{cooked, raw}` object from the `metaBlock` and `messagePart`. 25168 * 25169 * The `raw` text must have various character sequences escaped: 25170 * * "\" would otherwise indicate that the next character is a control character. 25171 * * "`" and "${" are template string control sequences that would otherwise prematurely indicate 25172 * the end of a message part. 25173 * * ":" inside a metablock would prematurely indicate the end of the metablock. 25174 * * ":" at the start of a messagePart with no metablock would erroneously indicate the start of a 25175 * metablock. 25176 * 25177 * @param metaBlock Any metadata that should be prepended to the string 25178 * @param messagePart The message part of the string 25179 */ 25180 25181 25182function createCookedRawString(metaBlock, messagePart, range) { 25183 if (metaBlock === '') { 25184 return { 25185 cooked: messagePart, 25186 raw: escapeForTemplateLiteral(escapeStartingColon(escapeSlashes(messagePart))), 25187 range 25188 }; 25189 } else { 25190 return { 25191 cooked: `:${metaBlock}:${messagePart}`, 25192 raw: escapeForTemplateLiteral(`:${escapeColons(escapeSlashes(metaBlock))}:${escapeSlashes(messagePart)}`), 25193 range 25194 }; 25195 } 25196} 25197
25198class ExternalExpr extends Expression { 25199 constructor(value, type, typeParams = null, sourceSpan) { 25200 super(type, sourceSpan); 25201 this.value = value; 25202 this.typeParams = typeParams; 25203 } 25204 25205 isEquivalent(e) { 25206 return e instanceof ExternalExpr && this.value.name === e.value.name && this.value.moduleName === e.value.moduleName && this.value.runtime === e.value.runtime; 25207 } 25208 25209 isConstant() { 25210 return false; 25211 } 25212 25213 visitExpression(visitor, context) { 25214 return visitor.visitExternalExpr(this, context); 25215 } 25216 25217} 25218 25219class ExternalReference { 25220 constructor(moduleName, name, runtime) { 25221 this.moduleName = moduleName; 25222 this.name = name; 25223 this.runtime = runtime; 25224 } 25225 25226} 25227 25228class ConditionalExpr extends Expression { 25229 constructor(condition, trueCase, falseCase = null, type, sourceSpan) { 25230 super(type || trueCase.type, sourceSpan); 25231 this.condition = condition; 25232 this.falseCase = falseCase; 25233 this.trueCase = trueCase; 25234 } 25235 25236 isEquivalent(e) { 25237 return e instanceof ConditionalExpr && this.condition.isEquivalent(e.condition) && this.trueCase.isEquivalent(e.trueCase) && nullSafeIsEquivalent(this.falseCase, e.falseCase); 25238 } 25239 25240 isConstant() { 25241 return false; 25242 } 25243 25244 visitExpression(visitor, context) { 25245 return visitor.visitConditionalExpr(this, context); 25246 } 25247 25248} 25249 25250class NotExpr extends Expression { 25251 constructor(condition, sourceSpan) { 25252 super(BOOL_TYPE, sourceSpan); 25253 this.condition = condition; 25254 } 25255 25256 isEquivalent(e) { 25257 return e instanceof NotExpr && this.condition.isEquivalent(e.condition); 25258 } 25259 25260 isConstant() { 25261 return false; 25262 } 25263 25264 visitExpression(visitor, context) { 25265 return visitor.visitNotExpr(this, context); 25266 } 25267 25268} 25269 25270class FnParam { 25271 constructor(name, type = null) { 25272 this.name = name; 25273 this.type = type; 25274 } 25275 25276 isEquivalent(param) { 25277 return this.name === param.name; 25278 } 25279 25280} 25281 25282class FunctionExpr extends Expression { 25283 constructor(params, statements, type, sourceSpan, name) { 25284 super(type, sourceSpan); 25285 this.params = params; 25286 this.statements = statements; 25287 this.name = name; 25288 } 25289 25290 isEquivalent(e) { 25291 return e instanceof FunctionExpr && areAllEquivalent(this.params, e.params) && areAllEquivalent(this.statements, e.statements); 25292 } 25293 25294 isConstant() { 25295 return false; 25296 } 25297 25298 visitExpression(visitor, context) { 25299 return visitor.visitFunctionExpr(this, context); 25300 } 25301 25302 toDeclStmt(name, modifiers) { 25303 return new DeclareFunctionStmt(name, this.params, this.statements, this.type, modifiers, this.sourceSpan); 25304 } 25305 25306} 25307 25308class UnaryOperatorExpr extends Expression { 25309 constructor(operator, expr, type, sourceSpan, parens = true) { 25310 super(type || NUMBER_TYPE, sourceSpan); 25311 this.operator = operator; 25312 this.expr = expr; 25313 this.parens = parens; 25314 } 25315 25316 isEquivalent(e) { 25317 return e instanceof UnaryOperatorExpr && this.operator === e.operator && this.expr.isEquivalent(e.expr); 25318 } 25319 25320 isConstant() { 25321 return false; 25322 } 25323 25324 visitExpression(visitor, context) { 25325 return visitor.visitUnaryOperatorExpr(this, context); 25326 } 25327 25328} 25329 25330class BinaryOperatorExpr extends Expression { 25331 constructor(operator, lhs, rhs, type, sourceSpan, parens = true) { 25332 super(type || lhs.type, sourceSpan); 25333 this.operator = operator; 25334 this.rhs = rhs; 25335 this.parens = parens; 25336 this.lhs = lhs; 25337 } 25338 25339 isEquivalent(e) { 25340 return e instanceof BinaryOperatorExpr && this.operator === e.operator && this.lhs.isEquivalent(e.lhs) && this.rhs.isEquivalent(e.rhs); 25341 } 25342 25343 isConstant() { 25344 return false; 25345 } 25346 25347 visitExpression(visitor, context) { 25348 return visitor.visitBinaryOperatorExpr(this, context); 25349 } 25350 25351} 25352 25353class ReadPropExpr extends Expression { 25354 constructor(receiver, name, type, sourceSpan) { 25355 super(type, sourceSpan); 25356 this.receiver = receiver; 25357 this.name = name; 25358 } 25359 25360 isEquivalent(e) { 25361 return e instanceof ReadPropExpr && this.receiver.isEquivalent(e.receiver) && this.name === e.name; 25362 } 25363 25364 isConstant() { 25365 return false; 25366 } 25367 25368 visitExpression(visitor, context) { 25369 return visitor.visitReadPropExpr(this, context); 25370 } 25371 25372 set(value) { 25373 return new WritePropExpr(this.receiver, this.name, value, null, this.sourceSpan); 25374 } 25375 25376} 25377
25378class ReadKeyExpr extends Expression { 25379 constructor(receiver, index, type, sourceSpan) { 25380 super(type, sourceSpan); 25381 this.receiver = receiver; 25382 this.index = index; 25383 } 25384 25385 isEquivalent(e) { 25386 return e instanceof ReadKeyExpr && this.receiver.isEquivalent(e.receiver) && this.index.isEquivalent(e.index); 25387 } 25388 25389 isConstant() { 25390 return false; 25391 } 25392 25393 visitExpression(visitor, context) { 25394 return visitor.visitReadKeyExpr(this, context); 25395 } 25396 25397 set(value) { 25398 return new WriteKeyExpr(this.receiver, this.index, value, null, this.sourceSpan); 25399 } 25400 25401} 25402 25403class LiteralArrayExpr extends Expression { 25404 constructor(entries, type, sourceSpan) { 25405 super(type, sourceSpan); 25406 this.entries = entries; 25407 } 25408 25409 isConstant() { 25410 return this.entries.every(e => e.isConstant()); 25411 } 25412 25413 isEquivalent(e) { 25414 return e instanceof LiteralArrayExpr && areAllEquivalent(this.entries, e.entries); 25415 } 25416 25417 visitExpression(visitor, context) { 25418 return visitor.visitLiteralArrayExpr(this, context); 25419 } 25420 25421} 25422 25423class LiteralMapEntry { 25424 constructor(key, value, quoted) { 25425 this.key = key; 25426 this.value = value; 25427 this.quoted = quoted; 25428 } 25429 25430 isEquivalent(e) { 25431 return this.key === e.key && this.value.isEquivalent(e.value); 25432 } 25433 25434} 25435 25436class LiteralMapExpr extends Expression { 25437 constructor(entries, type, sourceSpan) { 25438 super(type, sourceSpan); 25439 this.entries = entries; 25440 this.valueType = null; 25441 25442 if (type) { 25443 this.valueType = type.valueType; 25444 } 25445 } 25446 25447 isEquivalent(e) { 25448 return e instanceof LiteralMapExpr && areAllEquivalent(this.entries, e.entries); 25449 } 25450 25451 isConstant() { 25452 return this.entries.every(e => e.value.isConstant()); 25453 } 25454 25455 visitExpression(visitor, context) { 25456 return visitor.visitLiteralMapExpr(this, context); 25457 } 25458 25459} 25460 25461class CommaExpr extends Expression { 25462 constructor(parts, sourceSpan) { 25463 super(parts[parts.length - 1].type, sourceSpan); 25464 this.parts = parts; 25465 } 25466 25467 isEquivalent(e) { 25468 return e instanceof CommaExpr && areAllEquivalent(this.parts, e.parts); 25469 } 25470 25471 isConstant() { 25472 return false; 25473 } 25474 25475 visitExpression(visitor, context) { 25476 return visitor.visitCommaExpr(this, context); 25477 } 25478 25479} 25480 25481const NULL_EXPR = new LiteralExpr(null, null, null); 25482const TYPED_NULL_EXPR = new LiteralExpr(null, INFERRED_TYPE, null); //// Statements 25483 25484var StmtModifier; 25485 25486(function (StmtModifier) { 25487 StmtModifier[StmtModifier["None"] = 0] = "None"; 25488 StmtModifier[StmtModifier["Final"] = 1] = "Final"; 25489 StmtModifier[StmtModifier["Private"] = 2] = "Private"; 25490 StmtModifier[StmtModifier["Exported"] = 4] = "Exported"; 25491 StmtModifier[StmtModifier["Static"] = 8] = "Static"; 25492})(StmtModifier || (StmtModifier = {})); 25493 25494class LeadingComment { 25495 constructor(text, multiline, trailingNewline) { 25496 this.text = text; 25497 this.multiline = multiline; 25498 this.trailingNewline = trailingNewline; 25499 } 25500 25501 toString() { 25502 return this.multiline ? ` ${this.text} ` : this.text; 25503 } 25504 25505} 25506 25507class JSDocComment extends LeadingComment { 25508 constructor(tags) { 25509 super('', 25510 /* multiline */ 25511 true, 25512 /* trailingNewline */ 25513 true); 25514 this.tags = tags; 25515 } 25516 25517 toString() { 25518 return serializeTags(this.tags); 25519 } 25520 25521} 25522 25523class Statement { 25524 constructor(modifiers = StmtModifier.None, sourceSpan = null, leadingComments) { 25525 this.modifiers = modifiers; 25526 this.sourceSpan = sourceSpan; 25527 this.leadingComments = leadingComments; 25528 } 25529 25530 hasModifier(modifier) { 25531 return (this.modifiers & modifier) !== 0; 25532 } 25533 25534 addLeadingComment(leadingComment) { 25535 this.leadingComments = this.leadingComments ?? []; 25536 this.leadingComments.push(leadingComment); 25537 } 25538 25539} 25540 25541class DeclareVarStmt extends Statement { 25542 constructor(name, value, type, modifiers, sourceSpan, leadingComments) { 25543 super(modifiers, sourceSpan, leadingComments); 25544 this.name = name; 25545 this.value = value; 25546 this.type = type || value && value.type || null; 25547 } 25548 25549 isEquivalent(stmt) { 25550 return stmt instanceof DeclareVarStmt && this.name === stmt.name && (this.value ? !!stmt.value && this.value.isEquivalent(stmt.value) : !stmt.value); 25551 } 25552 25553 visitStatement(visitor, context) { 25554 return visitor.visitDeclareVarStmt(this, context); 25555 } 25556 25557} 25558 25559class DeclareFunctionStmt extends Statement { 25560 constructor(name, params, statements, type, modifiers, sourceSpan, leadingComments) { 25561 super(modifiers, sourceSpan, leadingComments); 25562 this.name = name; 25563 this.params = params; 25564 this.statements = statements; 25565 this.type = type || null; 25566 } 25567 25568 isEquivalent(stmt) { 25569 return stmt instanceof DeclareFunctionStmt && areAllEquivalent(this.params, stmt.params) && areAllEquivalent(this.statements, stmt.statements); 25570 } 25571
25572 visitStatement(visitor, context) { 25573 return visitor.visitDeclareFunctionStmt(this, context); 25574 } 25575 25576} 25577 25578class ExpressionStatement extends Statement { 25579 constructor(expr, sourceSpan, leadingComments) { 25580 super(StmtModifier.None, sourceSpan, leadingComments); 25581 this.expr = expr; 25582 } 25583 25584 isEquivalent(stmt) { 25585 return stmt instanceof ExpressionStatement && this.expr.isEquivalent(stmt.expr); 25586 } 25587 25588 visitStatement(visitor, context) { 25589 return visitor.visitExpressionStmt(this, context); 25590 } 25591 25592} 25593 25594class ReturnStatement extends Statement { 25595 constructor(value, sourceSpan = null, leadingComments) { 25596 super(StmtModifier.None, sourceSpan, leadingComments); 25597 this.value = value; 25598 } 25599 25600 isEquivalent(stmt) { 25601 return stmt instanceof ReturnStatement && this.value.isEquivalent(stmt.value); 25602 } 25603 25604 visitStatement(visitor, context) { 25605 return visitor.visitReturnStmt(this, context); 25606 } 25607 25608} 25609 25610class IfStmt extends Statement { 25611 constructor(condition, trueCase, falseCase = [], sourceSpan, leadingComments) { 25612 super(StmtModifier.None, sourceSpan, leadingComments); 25613 this.condition = condition; 25614 this.trueCase = trueCase; 25615 this.falseCase = falseCase; 25616 } 25617 25618 isEquivalent(stmt) { 25619 return stmt instanceof IfStmt && this.condition.isEquivalent(stmt.condition) && areAllEquivalent(this.trueCase, stmt.trueCase) && areAllEquivalent(this.falseCase, stmt.falseCase); 25620 } 25621 25622 visitStatement(visitor, context) { 25623 return visitor.visitIfStmt(this, context); 25624 } 25625 25626} 25627 25628class RecursiveAstVisitor$1 { 25629 visitType(ast, context) { 25630 return ast; 25631 } 25632 25633 visitExpression(ast, context) { 25634 if (ast.type) { 25635 ast.type.visitType(this, context); 25636 } 25637 25638 return ast; 25639 } 25640 25641 visitBuiltinType(type, context) { 25642 return this.visitType(type, context); 25643 } 25644 25645 visitExpressionType(type, context) { 25646 type.value.visitExpression(this, context); 25647 25648 if (type.typeParams !== null) { 25649 type.typeParams.forEach(param => this.visitType(param, context)); 25650 } 25651 25652 return this.visitType(type, context); 25653 } 25654 25655 visitArrayType(type, context) { 25656 return this.visitType(type, context); 25657 } 25658 25659 visitMapType(type, context) { 25660 return this.visitType(type, context); 25661 } 25662 25663 visitWrappedNodeExpr(ast, context) { 25664 return ast; 25665 } 25666 25667 visitTypeofExpr(ast, context) { 25668 return this.visitExpression(ast, context); 25669 } 25670 25671 visitReadVarExpr(ast, context) { 25672 return this.visitExpression(ast, context); 25673 } 25674 25675 visitWriteVarExpr(ast, context) { 25676 ast.value.visitExpression(this, context); 25677 return this.visitExpression(ast, context); 25678 } 25679 25680 visitWriteKeyExpr(ast, context) { 25681 ast.receiver.visitExpression(this, context); 25682 ast.index.visitExpression(this, context); 25683 ast.value.visitExpression(this, context); 25684 return this.visitExpression(ast, context); 25685 } 25686 25687 visitWritePropExpr(ast, context) { 25688 ast.receiver.visitExpression(this, context); 25689 ast.value.visitExpression(this, context); 25690 return this.visitExpression(ast, context); 25691 } 25692 25693 visitInvokeFunctionExpr(ast, context) { 25694 ast.fn.visitExpression(this, context); 25695 this.visitAllExpressions(ast.args, context); 25696 return this.visitExpression(ast, context); 25697 } 25698 25699 visitTaggedTemplateExpr(ast, context) { 25700 ast.tag.visitExpression(this, context); 25701 this.visitAllExpressions(ast.template.expressions, context); 25702 return this.visitExpression(ast, context); 25703 } 25704 25705 visitInstantiateExpr(ast, context) { 25706 ast.classExpr.visitExpression(this, context); 25707 this.visitAllExpressions(ast.args, context); 25708 return this.visitExpression(ast, context); 25709 } 25710 25711 visitLiteralExpr(ast, context) { 25712 return this.visitExpression(ast, context); 25713 } 25714 25715 visitLocalizedString(ast, context) { 25716 return this.visitExpression(ast, context); 25717 } 25718 25719 visitExternalExpr(ast, context) { 25720 if (ast.typeParams) { 25721 ast.typeParams.forEach(type => type.visitType(this, context)); 25722 } 25723 25724 return this.visitExpression(ast, context); 25725 } 25726 25727 visitConditionalExpr(ast, context) { 25728 ast.condition.visitExpression(this, context); 25729 ast.trueCase.visitExpression(this, context); 25730 ast.falseCase.visitExpression(this, context); 25731 return this.visitExpression(ast, context); 25732 } 25733 25734 visitNotExpr(ast, context) { 25735 ast.condition.visitExpression(this, context); 25736 return this.visitExpression(ast, context); 25737 } 25738 25739 visitFunctionExpr(ast, context) { 25740 this.visitAllStatements(ast.statements, context); 25741 return this.visitExpression(ast, context); 25742 } 25743 25744 visitUnaryOperatorExpr(ast, context) { 25745 ast.expr.visitExpression(this, context); 25746 return this.visitExpression(ast, context); 25747 } 25748 25749 visitBinaryOperatorExpr(ast, context) { 25750 ast.lhs.visitExpression(this, context); 25751 ast.rhs.visitExpression(this, context); 25752 return this.visitExpression(ast, context); 25753 } 25754 25755 visitReadPropExpr(ast, context) { 25756 ast.receiver.visitExpression(this, context); 25757 return this.visitExpression(ast, context); 25758 } 25759 25760 visitReadKeyExpr(ast, context) { 25761 ast.receiver.visitExpression(this, context); 25762 ast.index.visitExpression(this, context); 25763 return this.visitExpression(ast, context); 25764 } 25765 25766 visitLiteralArrayExpr(ast, context) { 25767 this.visitAllExpressions(ast.entries, context); 25768 return this.visitExpression(ast, context); 25769 } 25770 25771 visitLiteralMapExpr(ast, context) {
25772 ast.entries.forEach(entry => entry.value.visitExpression(this, context)); 25773 return this.visitExpression(ast, context); 25774 } 25775 25776 visitCommaExpr(ast, context) { 25777 this.visitAllExpressions(ast.parts, context); 25778 return this.visitExpression(ast, context); 25779 } 25780 25781 visitAllExpressions(exprs, context) { 25782 exprs.forEach(expr => expr.visitExpression(this, context)); 25783 } 25784 25785 visitDeclareVarStmt(stmt, context) { 25786 if (stmt.value) { 25787 stmt.value.visitExpression(this, context); 25788 } 25789 25790 if (stmt.type) { 25791 stmt.type.visitType(this, context); 25792 } 25793 25794 return stmt; 25795 } 25796 25797 visitDeclareFunctionStmt(stmt, context) { 25798 this.visitAllStatements(stmt.statements, context); 25799 25800 if (stmt.type) { 25801 stmt.type.visitType(this, context); 25802 } 25803 25804 return stmt; 25805 } 25806 25807 visitExpressionStmt(stmt, context) { 25808 stmt.expr.visitExpression(this, context); 25809 return stmt; 25810 } 25811 25812 visitReturnStmt(stmt, context) { 25813 stmt.value.visitExpression(this, context); 25814 return stmt; 25815 } 25816 25817 visitIfStmt(stmt, context) { 25818 stmt.condition.visitExpression(this, context); 25819 this.visitAllStatements(stmt.trueCase, context); 25820 this.visitAllStatements(stmt.falseCase, context); 25821 return stmt; 25822 } 25823 25824 visitAllStatements(stmts, context) { 25825 stmts.forEach(stmt => stmt.visitStatement(this, context)); 25826 } 25827 25828} 25829 25830function leadingComment(text, multiline = false, trailingNewline = true) { 25831 return new LeadingComment(text, multiline, trailingNewline); 25832} 25833 25834function jsDocComment(tags = []) { 25835 return new JSDocComment(tags); 25836} 25837 25838function variable(name, type, sourceSpan) { 25839 return new ReadVarExpr(name, type, sourceSpan); 25840} 25841 25842function importExpr(id, typeParams = null, sourceSpan) { 25843 return new ExternalExpr(id, null, typeParams, sourceSpan); 25844} 25845 25846function importType(id, typeParams, typeModifiers) { 25847 return id != null ? expressionType(importExpr(id, typeParams, null), typeModifiers) : null; 25848} 25849 25850function expressionType(expr, typeModifiers, typeParams) { 25851 return new ExpressionType(expr, typeModifiers, typeParams); 25852} 25853 25854function typeofExpr(expr) { 25855 return new TypeofExpr(expr); 25856} 25857 25858function literalArr(values, type, sourceSpan) { 25859 return new LiteralArrayExpr(values, type, sourceSpan); 25860} 25861 25862function literalMap(values, type = null) { 25863 return new LiteralMapExpr(values.map(e => new LiteralMapEntry(e.key, e.value, e.quoted)), type, null); 25864} 25865 25866function unary(operator, expr, type, sourceSpan) { 25867 return new UnaryOperatorExpr(operator, expr, type, sourceSpan); 25868} 25869 25870function not(expr, sourceSpan) { 25871 return new NotExpr(expr, sourceSpan); 25872} 25873 25874function fn(params, body, type, sourceSpan, name) { 25875 return new FunctionExpr(params, body, type, sourceSpan, name); 25876} 25877 25878function ifStmt(condition, thenClause, elseClause, sourceSpan, leadingComments) { 25879 return new IfStmt(condition, thenClause, elseClause, sourceSpan, leadingComments); 25880} 25881 25882function taggedTemplate(tag, template, type, sourceSpan) { 25883 return new TaggedTemplateExpr(tag, template, type, sourceSpan); 25884} 25885 25886function literal(value, type, sourceSpan) { 25887 return new LiteralExpr(value, type, sourceSpan); 25888} 25889 25890function localizedString(metaBlock, messageParts, placeholderNames, expressions, sourceSpan) { 25891 return new LocalizedString(metaBlock, messageParts, placeholderNames, expressions, sourceSpan); 25892} 25893 25894function isNull(exp) { 25895 return exp instanceof LiteralExpr && exp.value === null; 25896} 25897/* 25898 * Serializes a `Tag` into a string. 25899 * Returns a string like " @foo {bar} baz" (note the leading whitespace before `@foo`). 25900 */ 25901 25902 25903function tagToString(tag) { 25904 let out = ''; 25905 25906 if (tag.tagName) { 25907 out += ` @${tag.tagName}`; 25908 } 25909 25910 if (tag.text) { 25911 if (tag.text.match(/\/\*|\*\//)) { 25912 throw new Error('JSDoc text cannot contain "/*" and "*/"'); 25913 } 25914 25915 out += ' ' + tag.text.replace(/@/g, '\\@'); 25916 } 25917 25918 return out; 25919} 25920 25921function serializeTags(tags) { 25922 if (tags.length === 0) return ''; 25923 25924 if (tags.length === 1 && tags[0].tagName && !tags[0].text) { 25925 // The JSDOC comment is a single simple tag: e.g `/** @tagname */`. 25926 return `*${tagToString(tags[0])} `; 25927 } 25928 25929 let out = '*\n'; 25930 25931 for (const tag of tags) { 25932 out += ' *'; // If the tagToString is multi-line, insert " * " prefixes on lines. 25933 25934 out += tagToString(tag).replace(/\n/g, '\n * '); 25935 out += '\n'; 25936 } 25937 25938 out += ' '; 25939 return out; 25940} 25941 25942var output_ast = /*#__PURE__*/Object.freeze({ 25943 __proto__: null, 25944 25945 get TypeModifier() { 25946 return TypeModifier; 25947 }, 25948 25949 Type: Type, 25950 25951 get BuiltinTypeName() { 25952 return BuiltinTypeName; 25953 }, 25954 25955 BuiltinType: BuiltinType, 25956 ExpressionType: ExpressionType, 25957 ArrayType: ArrayType, 25958 MapType: MapType, 25959 DYNAMIC_TYPE: DYNAMIC_TYPE, 25960 INFERRED_TYPE: INFERRED_TYPE, 25961 BOOL_TYPE: BOOL_TYPE, 25962 INT_TYPE: INT_TYPE, 25963 NUMBER_TYPE: NUMBER_TYPE, 25964 STRING_TYPE: STRING_TYPE, 25965 FUNCTION_TYPE: FUNCTION_TYPE, 25966 NONE_TYPE: NONE_TYPE, 25967 25968 get UnaryOperator() { 25969 return UnaryOperator; 25970 }, 25971 25972 get BinaryOperator() { 25973 return BinaryOperator; 25974 }, 25975 25976 nullSafeIsEquivalent: nullSafeIsEquivalent, 25977 areAllEquivalent: areAllEquivalent, 25978 Expression: Expression, 25979 ReadVarExpr: ReadVarExpr, 25980 TypeofExpr: TypeofExpr, 25981 WrappedNodeExpr: WrappedNodeExpr, 25982 WriteVarExpr: WriteVarExpr, 25983 WriteKeyExpr: WriteKeyExpr, 25984 WritePropExpr: WritePropExpr, 25985 InvokeFunctionExpr: InvokeFunctionExpr, 25986 TaggedTemplateExpr: TaggedTemplateExpr, 25987 InstantiateExpr: InstantiateExpr, 25988 LiteralExpr: LiteralExpr,
25989 TemplateLiteral: TemplateLiteral, 25990 TemplateLiteralElement: TemplateLiteralElement, 25991 LiteralPiece: LiteralPiece, 25992 PlaceholderPiece: PlaceholderPiece, 25993 LocalizedString: LocalizedString, 25994 ExternalExpr: ExternalExpr, 25995 ExternalReference: ExternalReference, 25996 ConditionalExpr: ConditionalExpr, 25997 NotExpr: NotExpr, 25998 FnParam: FnParam, 25999 FunctionExpr: FunctionExpr, 26000 UnaryOperatorExpr: UnaryOperatorExpr, 26001 BinaryOperatorExpr: BinaryOperatorExpr, 26002 ReadPropExpr: ReadPropExpr, 26003 ReadKeyExpr: ReadKeyExpr, 26004 LiteralArrayExpr: LiteralArrayExpr, 26005 LiteralMapEntry: LiteralMapEntry, 26006 LiteralMapExpr: LiteralMapExpr, 26007 CommaExpr: CommaExpr, 26008 NULL_EXPR: NULL_EXPR, 26009 TYPED_NULL_EXPR: TYPED_NULL_EXPR, 26010 26011 get StmtModifier() { 26012 return StmtModifier; 26013 }, 26014 26015 LeadingComment: LeadingComment, 26016 JSDocComment: JSDocComment, 26017 Statement: Statement, 26018 DeclareVarStmt: DeclareVarStmt, 26019 DeclareFunctionStmt: DeclareFunctionStmt, 26020 ExpressionStatement: ExpressionStatement, 26021 ReturnStatement: ReturnStatement, 26022 IfStmt: IfStmt, 26023 RecursiveAstVisitor: RecursiveAstVisitor$1, 26024 leadingComment: leadingComment, 26025 jsDocComment: jsDocComment, 26026 variable: variable, 26027 importExpr: importExpr, 26028 importType: importType, 26029 expressionType: expressionType, 26030 typeofExpr: typeofExpr, 26031 literalArr: literalArr, 26032 literalMap: literalMap, 26033 unary: unary, 26034 not: not, 26035 fn: fn, 26036 ifStmt: ifStmt, 26037 taggedTemplate: taggedTemplate, 26038 literal: literal, 26039 localizedString: localizedString, 26040 isNull: isNull 26041}); 26042/** 26043 * @license 26044 * Copyright Google LLC All Rights Reserved. 26045 * 26046 * Use of this source code is governed by an MIT-style license that can be 26047 * found in the LICENSE file at https://angular.io/license 26048 */ 26049 26050const CONSTANT_PREFIX = '_c'; 26051/** 26052 * `ConstantPool` tries to reuse literal factories when two or more literals are identical. 26053 * We determine whether literals are identical by creating a key out of their AST using the 26054 * `KeyVisitor`. This constant is used to replace dynamic expressions which can't be safely 26055 * converted into a key. E.g. given an expression `{foo: bar()}`, since we don't know what 26056 * the result of `bar` will be, we create a key that looks like `{foo: <unknown>}`. Note 26057 * that we use a variable, rather than something like `null` in order to avoid collisions. 26058 */ 26059 26060const UNKNOWN_VALUE_KEY = variable('<unknown>'); 26061/** 26062 * Context to use when producing a key. 26063 * 26064 * This ensures we see the constant not the reference variable when producing 26065 * a key. 26066 */ 26067 26068const KEY_CONTEXT = {}; 26069/** 26070 * Generally all primitive values are excluded from the `ConstantPool`, but there is an exclusion 26071 * for strings that reach a certain length threshold. This constant defines the length threshold for 26072 * strings. 26073 */ 26074 26075const POOL_INCLUSION_LENGTH_THRESHOLD_FOR_STRINGS = 50; 26076/** 26077 * A node that is a place-holder that allows the node to be replaced when the actual 26078 * node is known. 26079 * 26080 * This allows the constant pool to change an expression from a direct reference to 26081 * a constant to a shared constant. It returns a fix-up node that is later allowed to 26082 * change the referenced expression. 26083 */ 26084 26085class FixupExpression extends Expression { 26086 constructor(resolved) { 26087 super(resolved.type); 26088 this.resolved = resolved; 26089 this.original = resolved; 26090 } 26091 26092 visitExpression(visitor, context) { 26093 if (context === KEY_CONTEXT) { 26094 // When producing a key we want to traverse the constant not the 26095 // variable used to refer to it. 26096 return this.original.visitExpression(visitor, context); 26097 } else { 26098 return this.resolved.visitExpression(visitor, context); 26099 } 26100 } 26101 26102 isEquivalent(e) { 26103 return e instanceof FixupExpression && this.resolved.isEquivalent(e.resolved); 26104 } 26105 26106 isConstant() { 26107 return true; 26108 } 26109 26110 fixup(expression) { 26111 this.resolved = expression; 26112 this.shared = true; 26113 } 26114 26115} 26116/** 26117 * A constant pool allows a code emitter to share constant in an output context. 26118 * 26119 * The constant pool also supports sharing access to ivy definitions references. 26120 */ 26121 26122 26123class ConstantPool { 26124 constructor(isClosureCompilerEnabled = false) { 26125 this.isClosureCompilerEnabled = isClosureCompilerEnabled; 26126 this.statements = []; 26127 this.literals = new Map(); 26128 this.literalFactories = new Map(); 26129 this.nextNameIndex = 0; 26130 } 26131 26132 getConstLiteral(literal, forceShared) { 26133 if (literal instanceof LiteralExpr && !isLongStringLiteral(literal) || literal instanceof FixupExpression) {
26134 // Do no put simple literals into the constant pool or try to produce a constant for a 26135 // reference to a constant. 26136 return literal; 26137 } 26138 26139 const key = this.keyOf(literal); 26140 let fixup = this.literals.get(key); 26141 let newValue = false; 26142 26143 if (!fixup) { 26144 fixup = new FixupExpression(literal); 26145 this.literals.set(key, fixup); 26146 newValue = true; 26147 } 26148 26149 if (!newValue && !fixup.shared || newValue && forceShared) { 26150 // Replace the expression with a variable 26151 const name = this.freshName(); 26152 let definition; 26153 let usage; 26154 26155 if (this.isClosureCompilerEnabled && isLongStringLiteral(literal)) { 26156 // For string literals, Closure will **always** inline the string at 26157 // **all** usages, duplicating it each time. For large strings, this 26158 // unnecessarily bloats bundle size. To work around this restriction, we 26159 // wrap the string in a function, and call that function for each usage. 26160 // This tricks Closure into using inline logic for functions instead of 26161 // string literals. Function calls are only inlined if the body is small 26162 // enough to be worth it. By doing this, very large strings will be 26163 // shared across multiple usages, rather than duplicating the string at 26164 // each usage site. 26165 // 26166 // const myStr = function() { return "very very very long string"; }; 26167 // const usage1 = myStr(); 26168 // const usage2 = myStr(); 26169 definition = variable(name).set(new FunctionExpr([], // Params. 26170 [// Statements.
26171 new ReturnStatement(literal)])); 26172 usage = variable(name).callFn([]); 26173 } else { 26174 // Just declare and use the variable directly, without a function call 26175 // indirection. This saves a few bytes and avoids an unnecessary call. 26176 definition = variable(name).set(literal); 26177 usage = variable(name); 26178 } 26179 26180 this.statements.push(definition.toDeclStmt(INFERRED_TYPE, StmtModifier.Final)); 26181 fixup.fixup(usage); 26182 } 26183 26184 return fixup; 26185 } 26186 26187 getLiteralFactory(literal) { 26188 // Create a pure function that builds an array of a mix of constant and variable expressions 26189 if (literal instanceof LiteralArrayExpr) { 26190 const argumentsForKey = literal.entries.map(e => e.isConstant() ? e : UNKNOWN_VALUE_KEY); 26191 const key = this.keyOf(literalArr(argumentsForKey)); 26192 return this._getLiteralFactory(key, literal.entries, entries => literalArr(entries)); 26193 } else { 26194 const expressionForKey = literalMap(literal.entries.map(e => ({ 26195 key: e.key, 26196 value: e.value.isConstant() ? e.value : UNKNOWN_VALUE_KEY, 26197 quoted: e.quoted 26198 }))); 26199 const key = this.keyOf(expressionForKey); 26200 return this._getLiteralFactory(key, literal.entries.map(e => e.value), entries => literalMap(entries.map((value, index) => ({ 26201 key: literal.entries[index].key, 26202 value, 26203 quoted: literal.entries[index].quoted 26204 })))); 26205 } 26206 } 26207 26208 _getLiteralFactory(key, values, resultMap) { 26209 let literalFactory = this.literalFactories.get(key); 26210 const literalFactoryArguments = values.filter(e => !e.isConstant()); 26211 26212 if (!literalFactory) { 26213 const resultExpressions = values.map((e, index) => e.isConstant() ? this.getConstLiteral(e, true) : variable(`a${index}`)); 26214 const parameters = resultExpressions.filter(isVariable).map(e => new FnParam(e.name, DYNAMIC_TYPE)); 26215 const pureFunctionDeclaration = fn(parameters, [new ReturnStatement
26215(resultMap(resultExpressions))], INFERRED_TYPE); 26216 const name = this.freshName(); 26217 this.statements.push(variable(name).set(pureFunctionDeclaration).toDeclStmt(INFERRED_TYPE, StmtModifier.Final)); 26218 literalFactory = variable(name); 26219 this.literalFactories.set(key, literalFactory); 26220 } 26221 26222 return { 26223 literalFactory, 26224 literalFactoryArguments 26225 }; 26226 } 26227 /** 26228 * Produce a unique name. 26229 * 26230 * The name might be unique among different prefixes if any of the prefixes end in 26231 * a digit so the prefix should be a constant string (not based on user input) and 26232 * must not end in a digit. 26233 */ 26234 26235 26236 uniqueName(prefix) { 26237 return `${prefix}${this.nextNameIndex++}`; 26238 } 26239 26240 freshName() { 26241 return this.uniqueName(CONSTANT_PREFIX); 26242 } 26243 26244 keyOf(expression) { 26245 return expression.visitExpression(new KeyVisitor(), KEY_CONTEXT); 26246 } 26247 26248} 26249/** 26250 * Visitor used to determine if 2 expressions are equivalent and can be shared in the 26251 * `ConstantPool`. 26252 * 26253 * When the id (string) generated by the visitor is equal, expressions are considered equivalent. 26254 */ 26255 26256 26257class KeyVisitor { 26258 constructor() { 26259 this.visitWrappedNodeExpr = invalid$1; 26260 this.visitWriteVarExpr = invalid$1; 26261 this.visitWriteKeyExpr = invalid$1; 26262 this.visitWritePropExpr = invalid$1; 26263 this.visitInvokeFunctionExpr = invalid$1; 26264 this.visitTaggedTemplateExpr = invalid$1; 26265 this.visitInstantiateExpr = invalid$1; 26266 this.visitConditionalExpr = invalid$1; 26267 this.visitNotExpr = invalid$1; 26268 this.visitAssertNotNullExpr = invalid$1; 26269 this.visitCastExpr = invalid$1; 26270 this.visitFunctionExpr = invalid$1; 26271 this.visitUnaryOperatorExpr = invalid$1; 26272 this.visitBinaryOperatorExpr = invalid$1; 26273 this.visitReadPropExpr = invalid$1; 26274 this.visitReadKeyExpr = invalid$1; 26275 this.visitCommaExpr = invalid$1; 26276 this.visitLocalizedString = invalid$1; 26277 } 26278 26279 visitLiteralExpr(ast) { 26280 return `${typeof ast.value === 'string' ? '"' + ast.value + '"' : ast.value}`; 26281 } 26282 26283 visitLiteralArrayExpr(ast, context) { 26284 return `[${ast.entries.map(entry => entry.visitExpression(this, context)).join(',')}]`; 26285 } 26286 26287 visitLiteralMapExpr(ast, context) { 26288 const mapKey = entry => { 26289 const quote = entry.quoted ? '"' : ''; 26290 return `${quote}${entry.key}${quote}`; 26291 }; 26292 26293 const mapEntry = entry => `${mapKey(entry)}:${entry.value.visitExpression(this, context)}`; 26294 26295 return `{${ast.entries.map(mapEntry).join(',')}`; 26296 } 26297 26298 visitExternalExpr(ast) { 26299 return ast.value.moduleName ? `EX:${ast.value.moduleName}:${ast.value.name}` : `EX:${ast.value.runtime.name}`; 26300 } 26301 26302 visitReadVarExpr(node) { 26303 return `VAR:${node.name}`; 26304 } 26305 26306 visitTypeofExpr(node, context) { 26307 return `TYPEOF:${node.expr.visitExpression(this, context)}`; 26308 } 26309 26310} 26311
26312function invalid$1(arg) { 26313 throw new Error(`Invalid state: Visitor ${this.constructor.name} doesn't handle ${arg.constructor.name}`); 26314} 26315 26316function isVariable(e) { 26317 return e instanceof ReadVarExpr; 26318} 26319 26320function isLongStringLiteral(expr) { 26321 return expr instanceof LiteralExpr && typeof expr.value === 'string' && expr.value.length >= POOL_INCLUSION_LENGTH_THRESHOLD_FOR_STRINGS; 26322} 26323/** 26324 * @license 26325 * Copyright Google LLC All Rights Reserved. 26326 * 26327 * Use of this source code is governed by an MIT-style license that can be 26328 * found in the LICENSE file at https://angular.io/license 26329 */ 26330 26331 26332const CORE = '@angular/core'; 26333 26334class Identifiers {} 26335/* Methods */ 26336 26337 26338Identifiers.NEW_METHOD = 'factory'; 26339Identifiers.TRANSFORM_METHOD = 'transform'; 26340Identifiers.PATCH_DEPS = 'patchedDeps'; 26341Identifiers.core = { 26342 name: null, 26343 moduleName: CORE 26344}; 26345/* Instructions */ 26346 26347Identifiers.namespaceHTML = { 26348 name: 'ɵɵnamespaceHTML', 26349 moduleName: CORE 26350}; 26351Identifiers.namespaceMathML = { 26352 name: 'ɵɵnamespaceMathML', 26353 moduleName: CORE 26354}; 26355Identifiers.namespaceSVG = { 26356 name: 'ɵɵnamespaceSVG', 26357 moduleName: CORE 26358}; 26359Identifiers.element = { 26360 name: 'ɵɵelement', 26361 moduleName: CORE 26362}; 26363Identifiers.elementStart = { 26364 name: 'ɵɵelementStart', 26365 moduleName: CORE 26366}; 26367Identifiers.elementEnd = { 26368 name: 'ɵɵelementEnd', 26369 moduleName: CORE 26370}; 26371Identifiers.advance = { 26372 name: 'ɵɵadvance', 26373 moduleName: CORE 26374}; 26375Identifiers.syntheticHostProperty = { 26376 name: 'ɵɵsyntheticHostProperty', 26377 moduleName: CORE 26378}; 26379Identifiers.syntheticHostListener = { 26380 name: 'ɵɵsyntheticHostListener', 26381 moduleName: CORE 26382}; 26383Identifiers.attribute = { 26384 name: 'ɵɵattribute', 26385 moduleName: CORE 26386}; 26387Identifiers.attributeInterpolate1 = { 26388 name: 'ɵɵattributeInterpolate1', 26389 moduleName: CORE 26390}; 26391Identifiers.attributeInterpolate2 = { 26392 name: 'ɵɵattributeInterpolate2', 26393 moduleName: CORE 26394}; 26395Identifiers.attributeInterpolate3 = { 26396 name: 'ɵɵattributeInterpolate3', 26397 moduleName: CORE 26398}; 26399Identifiers.attributeInterpolate4 = { 26400 name: 'ɵɵattributeInterpolate4', 26401 moduleName: CORE 26402}; 26403Identifiers.attributeInterpolate5 = { 26404 name: 'ɵɵattributeInterpolate5', 26405 moduleName: CORE 26406}; 26407Identifiers.attributeInterpolate6 = { 26408 name: 'ɵɵattributeInterpolate6', 26409 moduleName: CORE 26410}; 26411Identifiers.attributeInterpolate7 = { 26412 name: 'ɵɵattributeInterpolate7', 26413 moduleName: CORE 26414}; 26415Identifiers.attributeInterpolate8 = { 26416 name: 'ɵɵattributeInterpolate8', 26417 moduleName: CORE 26418}; 26419Identifiers.attributeInterpolateV = { 26420 name: 'ɵɵattributeInterpolateV', 26421 moduleName: CORE 26422}; 26423Identifiers.classProp = { 26424 name: 'ɵɵclassProp', 26425 moduleName: CORE 26426}; 26427Identifiers.elementContainerStart = { 26428 name: 'ɵɵelementContainerStart', 26429 moduleName: CORE 26430}; 26431Identifiers.elementContainerEnd = { 26432 name: 'ɵɵelementContainerEnd', 26433 moduleName: CORE 26434}; 26435Identifiers.elementContainer = { 26436 name: 'ɵɵelementContainer', 26437 moduleName: CORE 26438}; 26439Identifiers.styleMap = { 26440 name: 'ɵɵstyleMap', 26441 moduleName: CORE 26442}; 26443Identifiers.styleMapInterpolate1 = { 26444 name: 'ɵɵstyleMapInterpolate1', 26445 moduleName: CORE 26446}; 26447Identifiers.styleMapInterpolate2 = { 26448 name: 'ɵɵstyleMapInterpolate2', 26449 moduleName: CORE 26450}; 26451Identifiers.styleMapInterpolate3 = { 26452 name: 'ɵɵstyleMapInterpolate3', 26453 moduleName: CORE 26454}; 26455Identifiers.styleMapInterpolate4 = { 26456 name: 'ɵɵstyleMapInterpolate4', 26457 moduleName: CORE 26458}; 26459Identifiers.styleMapInterpolate5 = { 26460 name: 'ɵɵstyleMapInterpolate5', 26461 moduleName: CORE 26462}; 26463Identifiers.styleMapInterpolate6 = { 26464 name: 'ɵɵstyleMapInterpolate6', 26465 moduleName: CORE 26466}; 26467Identifiers.styleMapInterpolate7 = { 26468 name: 'ɵɵstyleMapInterpolate7', 26469 moduleName: CORE 26470}; 26471Identifiers.styleMapInterpolate8 = { 26472 name: 'ɵɵstyleMapInterpolate8', 26473 moduleName: CORE 26474}; 26475Identifiers.styleMapInterpolateV = { 26476 name: 'ɵɵstyleMapInterpolateV', 26477 moduleName: CORE 26478}; 26479Identifiers.classMap = { 26480 name: 'ɵɵclassMap', 26481 moduleName: CORE 26482}; 26483Identifiers.classMapInterpolate1 = { 26484 name: 'ɵɵclassMapInterpolate1', 26485 moduleName: CORE 26486}; 26487Identifiers.classMapInterpolate2 = { 26488 name: 'ɵɵclassMapInterpolate2', 26489 moduleName: CORE 26490}; 26491Identifiers.classMapInterpolate3 = { 26492 name: 'ɵɵclassMapInterpolate3', 26493 moduleName: CORE 26494}; 26495Identifiers.classMapInterpolate4 = { 26496 name: 'ɵɵclassMapInterpolate4', 26497 moduleName: CORE 26498}; 26499Identifiers.classMapInterpolate5 = { 26500 name: 'ɵɵclassMapInterpolate5', 26501 moduleName: CORE 26502}; 26503Identifiers.classMapInterpolate6 = { 26504 name: 'ɵɵclassMapInterpolate6', 26505 moduleName: CORE 26506}; 26507Identifiers.classMapInterpolate7 = { 26508 name: 'ɵɵclassMapInterpolate7', 26509 moduleName: CORE 26510}; 26511Identifiers.classMapInterpolate8 = { 26512 name: 'ɵɵclassMapInterpolate8', 26513 moduleName: CORE 26514}; 26515Identifiers.classMapInterpolateV = { 26516 name: 'ɵɵclassMapInterpolateV', 26517 moduleName: CORE 26518}; 26519Identifiers.styleProp = { 26520 name: 'ɵɵstyleProp', 26521 moduleName: CORE 26522}; 26523Identifiers.stylePropInterpolate1 = { 26524 name: 'ɵɵstylePropInterpolate1', 26525 moduleName: CORE 26526}; 26527Identifiers.stylePropInterpolate2 = { 26528 name: 'ɵɵstylePropInterpolate2', 26529 moduleName: CORE 26530}; 26531Identifiers.stylePropInterpolate3 = { 26532 name: 'ɵɵstylePropInterpolate3', 26533 moduleName: CORE 26534}; 26535Identifiers.stylePropInterpolate4 = { 26536 name: 'ɵɵstylePropInterpolate4', 26537 moduleName: CORE 26538}; 26539Identifiers.stylePropInterpolate5 = { 26540 name: 'ɵɵstylePropInterpolate5', 26541 moduleName: CORE 26542}; 26543Identifiers.stylePropInterpolate6 = { 26544 name: 'ɵɵstylePropInterpolate6', 26545 moduleName: CORE 26546}; 26547Identifiers.stylePropInterpolate7 = { 26548 name: 'ɵɵstylePropInterpolate7', 26549 moduleName: CORE 26550}; 26551Identifiers.stylePropInterpolate8 = { 26552 name: 'ɵɵstylePropInterpolate8', 26553 moduleName: CORE 26554}; 26555Identifiers.stylePropInterpolateV = { 26556 name: 'ɵɵstylePropInterpolateV', 26557 moduleName: CORE 26558}; 26559Identifiers.nextContext = { 26560 name: 'ɵɵnextContext', 26561 moduleName: CORE 26562}; 26563Identifiers.resetView = {
26564 name: 'ɵɵresetView', 26565 moduleName: CORE 26566}; 26567Identifiers.templateCreate = { 26568 name: 'ɵɵtemplate', 26569 moduleName: CORE 26570}; 26571Identifiers.text = { 26572 name: 'ɵɵtext', 26573 moduleName: CORE 26574}; 26575Identifiers.enableBindings = { 26576 name: 'ɵɵenableBindings', 26577 moduleName: CORE 26578}; 26579Identifiers.disableBindings = { 26580 name: 'ɵɵdisableBindings', 26581 moduleName: CORE 26582}; 26583Identifiers.getCurrentView = { 26584 name: 'ɵɵgetCurrentView', 26585 moduleName: CORE 26586}; 26587Identifiers.textInterpolate = { 26588 name: 'ɵɵtextInterpolate', 26589 moduleName: CORE 26590}; 26591Identifiers.textInterpolate1 = { 26592 name: 'ɵɵtextInterpolate1', 26593 moduleName: CORE 26594}; 26595Identifiers.textInterpolate2 = { 26596 name: 'ɵɵtextInterpolate2', 26597 moduleName: CORE 26598}; 26599Identifiers.textInterpolate3 = { 26600 name: 'ɵɵtextInterpolate3', 26601 moduleName: CORE 26602}; 26603Identifiers.textInterpolate4 = { 26604 name: 'ɵɵtextInterpolate4', 26605 moduleName: CORE 26606}; 26607Identifiers.textInterpolate5 = { 26608 name: 'ɵɵtextInterpolate5', 26609 moduleName: CORE 26610}; 26611Identifiers.textInterpolate6 = { 26612 name: 'ɵɵtextInterpolate6', 26613 moduleName: CORE 26614}; 26615Identifiers.textInterpolate7 = { 26616 name: 'ɵɵtextInterpolate7', 26617 moduleName: CORE 26618}; 26619Identifiers.textInterpolate8 = { 26620 name: 'ɵɵtextInterpolate8', 26621 moduleName: CORE 26622}; 26623Identifiers.textInterpolateV = { 26624 name: 'ɵɵtextInterpolateV', 26625 moduleName: CORE 26626}; 26627Identifiers.restoreView = { 26628 name: 'ɵɵrestoreView', 26629 moduleName: CORE 26630}; 26631Identifiers.pureFunction0 = { 26632 name: 'ɵɵpureFunction0', 26633 moduleName: CORE 26634}; 26635Identifiers.pureFunction1 = { 26636 name: 'ɵɵpureFunction1', 26637 moduleName: CORE 26638}; 26639Identifiers.pureFunction2 = { 26640 name: 'ɵɵpureFunction2', 26641 moduleName: CORE 26642}; 26643Identifiers.pureFunction3 = { 26644 name: 'ɵɵpureFunction3', 26645 moduleName: CORE 26646}; 26647Identifiers.pureFunction4 = { 26648 name: 'ɵɵpureFunction4', 26649 moduleName: CORE 26650}; 26651Identifiers.pureFunction5 = { 26652 name: 'ɵɵpureFunction5', 26653 moduleName: CORE 26654}; 26655Identifiers.pureFunction6 = { 26656 name: 'ɵɵpureFunction6', 26657 moduleName: CORE 26658}; 26659Identifiers.pureFunction7 = { 26660 name: 'ɵɵpureFunction7', 26661 moduleName: CORE 26662}; 26663Identifiers.pureFunction8 = { 26664 name: 'ɵɵpureFunction8', 26665 moduleName: CORE 26666}; 26667Identifiers.pureFunctionV = { 26668 name: 'ɵɵpureFunctionV', 26669 moduleName: CORE 26670}; 26671Identifiers.pipeBind1 = { 26672 name: 'ɵɵpipeBind1', 26673 moduleName: CORE 26674}; 26675Identifiers.pipeBind2 = { 26676 name: 'ɵɵpipeBind2', 26677 moduleName: CORE 26678}; 26679Identifiers.pipeBind3 = { 26680 name: 'ɵɵpipeBind3', 26681 moduleName: CORE 26682}; 26683Identifiers.pipeBind4 = { 26684 name: 'ɵɵpipeBind4', 26685 moduleName: CORE 26686}; 26687Identifiers.pipeBindV = { 26688 name: 'ɵɵpipeBindV', 26689 moduleName: CORE 26690}; 26691Identifiers.hostProperty = { 26692 name: 'ɵɵhostProperty', 26693 moduleName: CORE 26694}; 26695Identifiers.property = { 26696 name: 'ɵɵproperty', 26697 moduleName: CORE 26698}; 26699Identifiers.propertyInterpolate = { 26700 name: 'ɵɵpropertyInterpolate', 26701 moduleName: CORE 26702}; 26703Identifiers.propertyInterpolate1 = { 26704 name: 'ɵɵpropertyInterpolate1', 26705 moduleName: CORE 26706}; 26707Identifiers.propertyInterpolate2 = { 26708 name: 'ɵɵpropertyInterpolate2', 26709 moduleName: CORE 26710}; 26711Identifiers.propertyInterpolate3 = { 26712 name: 'ɵɵpropertyInterpolate3', 26713 moduleName: CORE 26714}; 26715Identifiers.propertyInterpolate4 = { 26716 name: 'ɵɵpropertyInterpolate4', 26717 moduleName: CORE 26718}; 26719Identifiers.propertyInterpolate5 = { 26720 name: 'ɵɵpropertyInterpolate5', 26721 moduleName: CORE 26722}; 26723Identifiers.propertyInterpolate6 = { 26724 name: 'ɵɵpropertyInterpolate6', 26725 moduleName: CORE 26726}; 26727Identifiers.propertyInterpolate7 = { 26728 name: 'ɵɵpropertyInterpolate7', 26729 moduleName: CORE 26730}; 26731Identifiers.propertyInterpolate8 = { 26732 name: 'ɵɵpropertyInterpolate8', 26733 moduleName: CORE 26734}; 26735Identifiers.propertyInterpolateV = { 26736 name: 'ɵɵpropertyInterpolateV', 26737 moduleName: CORE 26738}; 26739Identifiers.i18n = { 26740 name: 'ɵɵi18n', 26741 moduleName: CORE 26742}; 26743Identifiers.i18nAttributes = { 26744 name: 'ɵɵi18nAttributes', 26745 moduleName: CORE 26746}; 26747Identifiers.i18nExp = { 26748 name: 'ɵɵi18nExp', 26749 moduleName: CORE 26750}; 26751Identifiers.i18nStart = { 26752 name: 'ɵɵi18nStart', 26753 moduleName: CORE 26754}; 26755Identifiers.i18nEnd = { 26756 name: 'ɵɵi18nEnd', 26757 moduleName: CORE 26758}; 26759Identifiers.i18nApply = { 26760 name: 'ɵɵi18nApply', 26761 moduleName: CORE 26762}; 26763Identifiers.i18nPostprocess = { 26764 name: 'ɵɵi18nPostprocess', 26765 moduleName: CORE 26766}; 26767Identifiers.pipe = { 26768 name: 'ɵɵpipe', 26769 moduleName: CORE 26770}; 26771Identifiers.projection = { 26772 name: 'ɵɵprojection', 26773 moduleName: CORE 26774}; 26775Identifiers.projectionDef = { 26776 name: 'ɵɵprojectionDef', 26777 moduleName: CORE 26778}; 26779Identifiers.reference = { 26780 name: 'ɵɵreference', 26781 moduleName: CORE 26782}; 26783Identifiers.inject = { 26784 name: 'ɵɵinject', 26785 moduleName: CORE 26786}; 26787Identifiers.injectAttribute = { 26788 name: 'ɵɵinjectAttribute', 26789 moduleName: CORE 26790}; 26791Identifiers.directiveInject = { 26792 name: 'ɵɵdirectiveInject', 26793 moduleName: CORE 26794}; 26795Identifiers.invalidFactory = { 26796 name: 'ɵɵinvalidFactory', 26797 moduleName: CORE 26798}; 26799Identifiers.invalidFactoryDep = { 26800 name: 'ɵɵinvalidFactoryDep', 26801 moduleName: CORE 26802}; 26803Identifiers.templateRefExtractor = { 26804 name: 'ɵɵtemplateRefExtractor', 26805 moduleName: CORE 26806}; 26807Identifiers.forwardRef = { 26808 name: 'forwardRef', 26809 moduleName: CORE 26810}; 26811Identifiers.resolveForwardRef = { 26812 name: 'resolveForwardRef', 26813 moduleName: CORE 26814}; 26815Identifiers.ɵɵdefineInjectable = { 26816 name: 'ɵɵdefineInjectable', 26817 moduleName: CORE 26818}; 26819Identifiers.declareInjectable = { 26820 name: 'ɵɵngDeclareInjectable', 26821 moduleName: CORE 26822}; 26823Identifiers.InjectableDeclaration = { 26824 name: 'ɵɵInjectableDeclaration', 26825 moduleName: CORE 26826}; 26827Identifiers.resolveWindow = { 26828 name: 'ɵɵresolveWindow', 26829 moduleName: CORE 26830}; 26831Identifiers.resolveDocument = { 26832 name: 'ɵɵresolveDocument', 26833 moduleName: CORE 26834}; 26835Identifiers.resolveBody = { 26836 name: 'ɵɵresolveBody', 26837 moduleName: CORE 26838}; 26839Identifiers.defineComponent = { 26840 name: 'ɵɵdefineComponent', 26841 moduleName: CORE 26842}; 26843Identifiers.declareComponent = { 26844 name: 'ɵɵngDeclareComponent', 26845 moduleName: CORE 26846}; 26847Identifiers.setComponentScope = { 26848 name: 'ɵɵsetComponentScope', 26849 moduleName: CORE 26850}; 26851Identifiers.ChangeDetectionStrategy = { 26852 name: 'ChangeDetectionStrategy', 26853 moduleName: CORE 26854}; 26855Identifiers.ViewEncapsulation = { 26856 name: 'ViewEncapsulation', 26857 moduleName: CORE 26858}; 26859Identifiers.ComponentDeclaration = { 26860 name: 'ɵɵComponentDeclaration', 26861 moduleName: CORE 26862}; 26863Identifiers.FactoryDeclaration = { 26864 name: 'ɵɵFactoryDeclaration', 26865 moduleName: CORE 26866}; 26867Identifiers.declareFactory = { 26868 name: 'ɵɵngDeclareFactory', 26869 moduleName: CORE 26870}; 26871Identifiers.FactoryTarget = { 26872 name: 'ɵɵFactoryTarget', 26873 moduleName: CORE 26874}; 26875Identifiers.defineDirective = { 26876 name: 'ɵɵdefineDirective', 26877 moduleName: CORE 26878}; 26879Identifiers.declareDirective = { 26880 name: 'ɵɵngDeclareDirective', 26881 moduleName: CORE 26882}; 26883Identifiers.DirectiveDeclaration = { 26884 name: 'ɵɵDirectiveDeclaration', 26885 moduleName: CORE 26886}; 26887Identifiers.InjectorDef = { 26888 name: 'ɵɵInjectorDef', 26889 moduleName: CORE 26890}; 26891Identifiers.InjectorDeclaration = { 26892 name: 'ɵɵInjectorDeclaration', 26893 moduleName: CORE 26894}; 26895Identifiers.defineInjector = { 26896 name: 'ɵɵdefineInjector', 26897 moduleName: CORE 26898}; 26899Identifiers.declareInjector = { 26900 name: 'ɵɵngDeclareInjector', 26901 moduleName: CORE 26902}; 26903Identifiers.NgModuleDeclaration = { 26904 name: 'ɵɵNgModuleDeclaration', 26905 moduleName: CORE 26906}; 26907Identifiers.ModuleWithProviders = { 26908 name: 'ModuleWithProviders', 26909 moduleName: CORE 26910}; 26911Identifiers.defineNgModule = { 26912 name: 'ɵɵdefineNgModule', 26913 moduleName: CORE 26914}; 26915Identifiers.declareNgModule = { 26916 name: 'ɵɵngDeclareNgModule', 26917 moduleName: CORE 26918}; 26919Identifiers.setNgModuleScope = { 26920 name: 'ɵɵsetNgModuleScope', 26921 moduleName: CORE 26922}; 26923Identifiers.registerNgModuleType = { 26924 name: 'ɵɵregisterNgModuleType', 26925 moduleName: CORE 26926}; 26927Identifiers.PipeDeclaration = { 26928 name: 'ɵɵPipeDeclaration', 26929 moduleName: CORE 26930}; 26931Identifiers.definePipe = { 26932 name: 'ɵɵdefinePipe', 26933 moduleName: CORE 26934}; 26935Identifiers.declarePipe = { 26936 name: 'ɵɵngDeclarePipe', 26937 moduleName: CORE 26938}; 26939Identifiers.declareClassMetadata = { 26940 name: 'ɵɵngDeclareClassMetadata', 26941 moduleName: CORE 26942}; 26943Identifiers.setClassMetadata = { 26944 name: 'ɵsetClassMetadata', 26945 moduleName: CORE 26946}; 26947Identifiers.queryRefresh = { 26948 name: 'ɵɵqueryRefresh', 26949 moduleName: CORE 26950}; 26951Identifiers.viewQuery = { 26952 name: 'ɵɵviewQuery', 26953 moduleName: CORE 26954}; 26955Identifiers.loadQuery = { 26956 name: 'ɵɵloadQuery', 26957 moduleName: CORE 26958}; 26959Identifiers.contentQuery = { 26960 name: 'ɵɵcontentQuery', 26961 moduleName: CORE 26962}; 26963Identifiers.NgOnChangesFeature = { 26964 name: 'ɵɵNgOnChangesFeature', 26965 moduleName: CORE 26966}; 26967Identifiers.InheritDefinitionFeature = { 26968 name: 'ɵɵInheritDefinitionFeature', 26969 moduleName: CORE 26970}; 26971Identifiers.CopyDefinitionFeature = { 26972 name: 'ɵɵCopyDefinitionFeature', 26973 moduleName: CORE 26974}; 26975Identifiers.StandaloneFeature = { 26976 name: 'ɵɵStandaloneFeature', 26977 moduleName: CORE 26978}; 26979Identifiers.ProvidersFeature = { 26980 name: 'ɵɵProvidersFeature', 26981 moduleName: CORE 26982}; 26983Identifiers.listener = { 26984 name: 'ɵɵlistener', 26985 moduleName: CORE 26986}; 26987Identifiers.getInheritedFactory = { 26988 name: 'ɵɵgetInheritedFactory', 26989 moduleName: CORE 26990}; // sanitization-related functions 26991 26992Identifiers.sanitizeHtml = { 26993 name: 'ɵɵsanitizeHtml', 26994 moduleName: CORE 26995}; 26996Identifiers.sanitizeStyle = { 26997 name: 'ɵɵsanitizeStyle', 26998 moduleName: CORE 26999}; 27000Identifiers.sanitizeResourceUrl = { 27001 name: 'ɵɵsanitizeResourceUrl', 27002 moduleName: CORE 27003}; 27004Identifiers.sanitizeScript = { 27005 name: 'ɵɵsanitizeScript', 27006 moduleName: CORE 27007}; 27008Identifiers.sanitizeUrl = { 27009 name: 'ɵɵsanitizeUrl', 27010 moduleName: CORE 27011}; 27012Identifiers.sanitizeUrlOrResourceUrl = { 27013 name: 'ɵɵsanitizeUrlOrResourceUrl', 27014 moduleName: CORE 27015}; 27016Identifiers.trustConstantHtml = {
27017 name: 'ɵɵtrustConstantHtml', 27018 moduleName: CORE 27019}; 27020Identifiers.trustConstantResourceUrl = { 27021 name: 'ɵɵtrustConstantResourceUrl', 27022 moduleName: CORE 27023}; 27024/** 27025 * @license 27026 * Copyright Google LLC All Rights Reserved. 27027 * 27028 * Use of this source code is governed by an MIT-style license that can be 27029 * found in the LICENSE file at https://angular.io/license 27030 */ 27031// https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit 27032 27033const VERSION$1 = 3; 27034const JS_B64_PREFIX = '# sourceMappingURL=data:application/json;base64,'; 27035 27036class SourceMapGenerator { 27037 constructor(file = null) { 27038 this.file = file; 27039 this.sourcesContent = new Map(); 27040 this.lines = []; 27041 this.lastCol0 = 0; 27042 this.hasMappings = false; 27043 } // The content is `null` when the content is expected to be loaded using the URL 27044 27045 27046 addSource(url, content = null) { 27047 if (!this.sourcesContent.has(url)) { 27048 this.sourcesContent.set(url, content); 27049 } 27050 27051 return this; 27052 } 27053 27054 addLine() { 27055 this.lines.push([]); 27056 this.lastCol0 = 0; 27057 return this; 27058 } 27059 27060 addMapping(col0, sourceUrl, sourceLine0, sourceCol0) { 27061 if (!this.currentLine) { 27062 throw new Error(`A line must be added before mappings can be added`); 27063 } 27064 27065 if (sourceUrl != null && !this.sourcesContent.has(sourceUrl)) { 27066 throw new Error(`Unknown source file "${sourceUrl}"`); 27067 } 27068 27069 if (col0 == null) { 27070 throw new Error(`The column in the generated code must be provided`); 27071 } 27072 27073 if (col0 < this.lastCol0) { 27074 throw new Error(`Mapping should be added in output order`); 27075 } 27076 27077 if (sourceUrl && (sourceLine0 == null || sourceCol0 == null)) { 27078 throw new Error(`The source location must be provided when a source url is provided`); 27079 } 27080 27081 this.hasMappings = true; 27082 this.lastCol0 = col0; 27083 this.currentLine.push({ 27084 col0, 27085 sourceUrl, 27086 sourceLine0, 27087 sourceCol0 27088 }); 27089 return this; 27090 } 27091 /** 27092 * @internal strip this from published d.ts files due to 27093 * https://github.com/microsoft/TypeScript/issues/36216 27094 */ 27095 27096 27097 get currentLine() { 27098 return this.lines.slice(-1)[0]; 27099 } 27100 27101 toJSON() { 27102 if (!this.hasMappings) { 27103 return null; 27104 } 27105 27106 const sourcesIndex = new Map(); 27107 const sources = []; 27108 const sourcesContent = []; 27109 Array.from(this.sourcesContent.keys()).forEach((url, i) => { 27110 sourcesIndex.set(url, i); 27111 sources.push(url); 27112 sourcesContent.push(this.sourcesContent.get(url) || null); 27113 }); 27114 let mappings = ''; 27115 let lastCol0 = 0; 27116 let lastSourceIndex = 0; 27117 let lastSourceLine0 = 0; 27118 let lastSourceCol0 = 0; 27119 this.lines.forEach(segments => { 27120 lastCol0 = 0; 27121 mappings += segments.map(segment => { 27122 // zero-based starting column of the line in the generated code 27123 let segAsStr = toBase64VLQ(segment.col0 - lastCol0); 27124 lastCol0 = segment.col0; 27125 27126 if (segment.sourceUrl != null) { 27127 // zero-based index into the âsourcesâ list 27128 segAsStr += toBase64VLQ(sourcesIndex.get(segment.sourceUrl) - lastSourceIndex); 27129 lastSourceIndex = sourcesIndex.get(segment.sourceUrl); // the zero-based starting line in the original source 27130 27131 segAsStr += toBase64VLQ(segment.sourceLine0 - lastSourceLine0); 27132 lastSourceLine0 = segment.sourceLine0; // the zero-based starting column in the original source 27133 27134 segAsStr += toBase64VLQ(segment.sourceCol0 - lastSourceCol0); 27135 lastSourceCol0 = segment.sourceCol0; 27136 } 27137 27138 return segAsStr; 27139 }).join(','); 27140 mappings += ';'; 27141 }); 27142 mappings = mappings.slice(0, -1); 27143 return { 27144 'file': this.file || '', 27145 'version': VERSION$1, 27146 'sourceRoot': '', 27147 'sources': sources, 27148 'sourcesContent': sourcesContent, 27149 'mappings': mappings 27150 }; 27151 } 27152 27153 toJsComment() { 27154 return this.hasMappings ? '//' + JS_B64_PREFIX + toBase64String(JSON.stringify(this, null, 0)) : ''; 27155 } 27156 27157} 27158 27159function toBase64String(value) { 27160 let b64 = ''; 27161 const encoded = utf8Encode(value); 27162 27163 for (let i = 0; i < encoded.length;) { 27164 const i1 = encoded[i++]; 27165 const i2 = i < encoded.length ? encoded[i++] : null; 27166 const i3 = i < encoded.length ? encoded[i++] : null; 27167 b64 += toBase64Digit(i1 >> 2); 27168 b64 += toBase64Digit((i1 & 3) << 4 | (i2 === null ? 0 : i2 >> 4)); 27169 b64 += i2 === null ? '=' : toBase64Digit((i2 & 15) << 2 | (i3 === null ? 0 : i3 >> 6)); 27170 b64 += i2 === null || i3 === null ? '=' : toBase64Digit(i3 & 63); 27171 } 27172 27173 return b64; 27174} 27175 27176function toBase64VLQ(value) { 27177 value = value < 0 ? (-value << 1) + 1 : value << 1; 27178 let out = ''; 27179 27180 do { 27181 let digit = value & 31; 27182 value = value >> 5; 27183 27184 if (value > 0) { 27185 digit = digit | 32; 27186 } 27187 27188 out += toBase64Digit(digit); 27189 } while (value > 0); 27190 27191 return out; 27192} 27193 27194const B64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
27194+/'; 27195 27196function toBase64Digit(value) { 27197 if (value < 0 || value >= 64) { 27198 throw new Error(`Can only encode value in the range [0, 63]`); 27199 } 27200 27201 return B64_DIGITS[value]; 27202} 27203/** 27204 * @license 27205 * Copyright Google LLC All Rights Reserved. 27206 * 27207 * Use of this source code is governed by an MIT-style license that can be 27208 * found in the LICENSE file at https://angular.io/license 27209 */ 27210 27211 27212const _SINGLE_QUOTE_ESCAPE_STRING_RE = /'|\\|\n|\r|\$/g; 27213const _LEGAL_IDENTIFIER_RE = /^[$A-Z_][0-9A-Z_$]*$/i; 27214const _INDENT_WITH = ' '; 27215 27216class _EmittedLine { 27217 constructor(indent) { 27218 this.indent = indent; 27219 this.partsLength = 0; 27220 this.parts = []; 27221 this.srcSpans = []; 27222 } 27223 27224} 27225 27226class EmitterVisitorContext { 27227 constructor(_indent) { 27228 this._indent = _indent; 27229 this._lines = [new _EmittedLine(_indent)]; 27230 } 27231 27232 static createRoot() { 27233 return new EmitterVisitorContext(0); 27234 } 27235 /** 27236 * @internal strip this from published d.ts files due to 27237 * https://github.com/microsoft/TypeScript/issues/36216 27238 */ 27239 27240 27241 get _currentLine() { 27242 return this._lines[this._lines.length - 1]; 27243 } 27244 27245 println(from, lastPart = '') { 27246 this.print(from || null, lastPart, true); 27247 } 27248 27249 lineIsEmpty() { 27250 return this._currentLine.parts.length === 0; 27251 } 27252 27253 lineLength() { 27254 return this._currentLine.indent * _INDENT_WITH.length + this._currentLine.partsLength; 27255 } 27256 27257 print(from, part, newLine = false) { 27258 if (part.length > 0) { 27259 this._currentLine.parts.push(part); 27260 27261 this._currentLine.partsLength += part.length; 27262 27263 this._currentLine.srcSpans.push(from && from.sourceSpan || null); 27264 } 27265 27266 if (newLine) { 27267 this._lines.push(new _EmittedLine(this._indent)); 27268 } 27269 } 27270 27271 removeEmptyLastLine() { 27272 if (this.lineIsEmpty()) { 27273 this._lines.pop(); 27274 } 27275 } 27276 27277 incIndent() { 27278 this._indent++; 27279 27280 if (this.lineIsEmpty()) { 27281 this._currentLine.indent = this._indent; 27282 } 27283 } 27284 27285 decIndent() { 27286 this._indent--; 27287 27288 if (this.lineIsEmpty()) { 27289 this._currentLine.indent = this._indent; 27290 } 27291 } 27292 27293 toSource() { 27294 return this.sourceLines.map(l => l.parts.length > 0 ? _createIndent(l.indent) + l.parts.join('') : '').join('\n'); 27295 } 27296 27297 toSourceMapGenerator(genFilePath, startsAtLine = 0) { 27298 const map = new SourceMapGenerator(genFilePath); 27299 let firstOffsetMapped = false; 27300 27301 const mapFirstOffsetIfNeeded = () => { 27302 if (!firstOffsetMapped) { 27303 // Add a single space so that tools won't try to load the file from disk. 27304 // Note: We are using virtual urls like `ng:///`, so we have to 27305 // provide a content here. 27306 map.addSource(genFilePath, ' ').addMapping(0, genFilePath, 0, 0); 27307 firstOffsetMapped = true; 27308 } 27309 }; 27310 27311 for (let i = 0; i < startsAtLine; i++) { 27312 map.addLine(); 27313 mapFirstOffsetIfNeeded(); 27314 } 27315 27316 this.sourceLines.forEach((line, lineIdx) => { 27317 map.addLine(); 27318 const spans = line.srcSpans; 27319 const parts = line.parts; 27320 let col0 = line.indent * _INDENT_WITH.length; 27321 let spanIdx = 0; // skip leading parts without source spans 27322 27323 while (spanIdx < spans.length && !spans[spanIdx]) { 27324 col0 += parts[spanIdx].length; 27325 spanIdx++; 27326 } 27327 27328 if (spanIdx < spans.length && lineIdx === 0 && col0 === 0) { 27329 firstOffsetMapped = true; 27330 } else { 27331 mapFirstOffsetIfNeeded(); 27332 } 27333 27334 while (spanIdx < spans.length) { 27335 const span = spans[spanIdx]; 27336 const source = span.start.file; 27337 const sourceLine = span.start.line; 27338 const sourceCol = span.start.col; 27339 map.addSource(source.url, source.content).addMapping(col0, source.url, sourceLine, sourceCol); 27340 col0 += parts[spanIdx].length; 27341 spanIdx++; // assign parts without span or the same span to the previous segment 27342 27343 while (spanIdx < spans.length && (span === spans[spanIdx] || !spans[spanIdx])) { 27344 col0 += parts[spanIdx].length; 27345 spanIdx++; 27346 } 27347 } 27348 }); 27349 return map; 27350 } 27351 27352 spanOf(line, column) { 27353 const emittedLine = this._lines[line]; 27354 27355 if (emittedLine) { 27356 let columnsLeft = column - _createIndent(emittedLine.indent).length; 27357 27358 for (let partIndex = 0; partIndex < emittedLine.parts.length; partIndex++) { 27359 const part = emittedLine.parts[partIndex]; 27360 27361 if (part.length > columnsLeft) { 27362 return emittedLine.srcSpans[partIndex]; 27363 } 27364 27365 columnsLeft -= part.length; 27366 } 27367 } 27368 27369 return null; 27370 } 27371 /** 27372 * @internal strip this from published d.ts files due to 27373 * https://github.com/microsoft/TypeScript/issues/36216 27374 */ 27375 27376 27377 get sourceLines() { 27378 if (this._lines.length && this._lines[this._lines.length - 1].parts.length === 0) { 27379 return this._lines.slice(0, -1); 27380 } 27381 27382 return this._lines; 27383 } 27384 27385} 27386 27387class AbstractEmitterVisitor { 27388 constructor(_escapeDollarInStrings) { 27389 this._escapeDollarInStrings = _escapeDollarInStrings; 27390 } 27391 27392 printLeadingComments(stmt, ctx) { 27393 if (stmt.leadingComments === undefined) { 27394 return; 27395 } 27396 27397 for (const comment of stmt.leadingComments) { 27398 if (comment instanceof JSDocComment) { 27399 ctx.print(stmt, `/*${comment.toString()}*/`, comment.trailingNewline); 27400 } else { 27401 if (comment.multiline) { 27402 ctx.print(stmt, `/* ${comment.text} */`, comment.trailingNewline); 27403 } else { 27404 comment.text.split('\n').forEach(line => { 27405 ctx.println(stmt, `// ${line}`); 27406 }); 27407 } 27408 } 27409 } 27410 } 27411 27412 visitExpressionStmt(stmt, ctx) { 27413 this.printLeadingComments(stmt, ctx); 27414 stmt.expr.visitExpression(this, ctx); 27415 ctx.println(stmt, ';'); 27416 return null; 27417 } 27418 27419 visitReturnStmt(stmt, ctx) { 27420 this.printLeadingComments(stmt, ctx); 27421 ctx.print(stmt, `return `); 27422 stmt.value.visitExpression(this, ctx); 27423 ctx.println(stmt, ';'); 27424 return null; 27425 } 27426 27427 visitIfStmt(stmt, ctx) { 27428 this.printLeadingComments(stmt, ctx); 27429 ctx.print(stmt, `if (`); 27430 stmt.condition.visitExpression(this, ctx); 27431 ctx.print(stmt, `) {`); 27432 const hasElseCase = stmt.falseCase != null && stmt.falseCase.length > 0; 27433 27434 if (stmt.trueCase.length <= 1 && !hasElseCase) { 27435 ctx.print(stmt, ` `);
27436 this.visitAllStatements(stmt.trueCase, ctx); 27437 ctx.removeEmptyLastLine(); 27438 ctx.print(stmt, ` `); 27439 } else { 27440 ctx.println(); 27441 ctx.incIndent(); 27442 this.visitAllStatements(stmt.trueCase, ctx); 27443 ctx.decIndent(); 27444 27445 if (hasElseCase) { 27446 ctx.println(stmt, `} else {`); 27447 ctx.incIndent(); 27448 this.visitAllStatements(stmt.falseCase, ctx); 27449 ctx.decIndent(); 27450 } 27451 } 27452 27453 ctx.println(stmt, `}`); 27454 return null; 27455 } 27456 27457 visitWriteVarExpr(expr, ctx) { 27458 const lineWasEmpty = ctx.lineIsEmpty(); 27459 27460 if (!lineWasEmpty) { 27461 ctx.print(expr, '('); 27462 } 27463 27464 ctx.print(expr, `${expr.name} = `); 27465 expr.value.visitExpression(this, ctx); 27466 27467 if (!lineWasEmpty) { 27468 ctx.print(expr, ')'); 27469 } 27470 27471 return null; 27472 } 27473 27474 visitWriteKeyExpr(expr, ctx) { 27475 const lineWasEmpty = ctx.lineIsEmpty(); 27476 27477 if (!lineWasEmpty) { 27478 ctx.print(expr, '('); 27479 } 27480 27481 expr.receiver.visitExpression(this, ctx); 27482 ctx.print(expr, `[`); 27483 expr.index.visitExpression(this, ctx); 27484 ctx.print(expr, `] = `); 27485 expr.value.visitExpression(this, ctx); 27486 27487 if (!lineWasEmpty) { 27488 ctx.print(expr, ')'); 27489 } 27490 27491 return null; 27492 } 27493 27494 visitWritePropExpr(expr, ctx) { 27495 const lineWasEmpty = ctx.lineIsEmpty(); 27496 27497 if (!lineWasEmpty) { 27498 ctx.print(expr, '('); 27499 } 27500 27501 expr.receiver.visitExpression(this, ctx); 27502 ctx.print(expr, `.${expr.name} = `); 27503 expr.value.visitExpression(this, ctx); 27504 27505 if (!lineWasEmpty) { 27506 ctx.print(expr, ')'); 27507 } 27508 27509 return null; 27510 } 27511 27512 visitInvokeFunctionExpr(expr, ctx) { 27513 expr.fn.visitExpression(this, ctx); 27514 ctx.print(expr, `(`); 27515 this.visitAllExpressions(expr.args, ctx, ','); 27516 ctx.print(expr, `)`); 27517 return null; 27518 } 27519 27520 visitTaggedTemplateExpr(expr, ctx) { 27521 expr.tag.visitExpression(this, ctx); 27522 ctx.print(expr, '`' + expr.template.elements[0].rawText); 27523 27524 for (let i = 1; i < expr.template.elements.length; i++) { 27525 ctx.print(expr, '${'); 27526 expr.template.expressions[i - 1].visitExpression(this, ctx); 27527 ctx.print(expr, `}${expr.template.elements[i].rawText}`); 27528 } 27529 27530 ctx.print(expr, '`'); 27531 return null; 27532 } 27533 27534 visitWrappedNodeExpr(ast, ctx) { 27535 throw new Error('Abstract emitter cannot visit WrappedNodeExpr.'); 27536 } 27537 27538 visitTypeofExpr(expr, ctx) { 27539 ctx.print(expr, 'typeof '); 27540 expr.expr.visitExpression(this, ctx); 27541 } 27542 27543 visitReadVarExpr(ast, ctx) { 27544 ctx.print(ast, ast.name); 27545 return null; 27546 } 27547 27548 visitInstantiateExpr(ast, ctx) { 27549 ctx.print(ast, `new `); 27550 ast.classExpr.visitExpression(this, ctx); 27551 ctx.print(ast, `(`); 27552 this.visitAllExpressions(ast.args, ctx, ','); 27553 ctx.print(ast, `)`); 27554 return null; 27555 } 27556 27557 visitLiteralExpr(ast, ctx) { 27558 const value = ast.value; 27559 27560 if (typeof value === 'string') { 27561 ctx.print(ast, escapeIdentifier(value, this._escapeDollarInStrings)); 27562 } else { 27563 ctx.print(ast, `${value}`); 27564 } 27565 27566 return null; 27567 } 27568 27569 visitLocalizedString(ast, ctx) { 27570 const head = ast.serializeI18nHead(); 27571 ctx.print(ast, '$localize `' + head.raw); 27572 27573 for (let i = 1; i < ast.messageParts.length; i++) { 27574 ctx.print(ast, '${'); 27575 ast.expressions[i - 1].visitExpression(this, ctx); 27576 ctx.print(ast, `}${ast.serializeI18nTemplatePart(i).raw}`); 27577 } 27578 27579 ctx.print(ast, '`'); 27580 return null; 27581 } 27582 27583 visitConditionalExpr(ast, ctx) { 27584 ctx.print(ast, `(`); 27585 ast.condition.visitExpression(this, ctx); 27586 ctx.print(ast, '? '); 27587 ast.trueCase.visitExpression(this, ctx); 27588 ctx.print(ast, ': '); 27589 ast.falseCase.visitExpression(this, ctx); 27590 ctx.print(ast, `)`); 27591 return null; 27592 } 27593 27594 visitNotExpr(ast, ctx) { 27595 ctx.print(ast, '!'); 27596 ast.condition.visitExpression(this, ctx); 27597 return null; 27598 } 27599 27600 visitUnaryOperatorExpr(ast, ctx) { 27601 let opStr; 27602 27603 switch (ast.operator) { 27604 case UnaryOperator.Plus: 27605 opStr = '+'; 27606 break; 27607 27608 case UnaryOperator.Minus: 27609 opStr = '-'; 27610 break; 27611 27612 default: 27613 throw new Error(`Unknown operator ${ast.operator}`); 27614 } 27615 27616 if (ast.parens) ctx.print(ast, `(`); 27617 ctx.print(ast, opStr); 27618 ast.expr.visitExpression(this, ctx); 27619 if (ast.parens) ctx.print(ast, `)`); 27620 return null; 27621 } 27622 27623 visitBinaryOperatorExpr(ast, ctx) { 27624 let opStr; 27625 27626 switch (ast.operator) { 27627 case BinaryOperator.Equals: 27628 opStr = '=='; 27629 break; 27630 27631 case BinaryOperator.Identical: 27632 opStr = '==='; 27633 break; 27634 27635 case BinaryOperator.NotEquals: 27636 opStr = '!='; 27637 break; 27638 27639 case BinaryOperator.NotIdentical: 27640 opStr = '!=='; 27641 break; 27642 27643 case BinaryOperator.And: 27644 opStr = '&&'; 27645 break; 27646 27647 case BinaryOperator.BitwiseAnd: 27648 opStr = '&'; 27649 break; 27650 27651 case BinaryOperator.Or: 27652 opStr = '||'; 27653 break; 27654 27655 case BinaryOperator.Plus: 27656 opStr = '+'; 27657 break; 27658 27659 case BinaryOperator.Minus: 27660 opStr = '-'; 27661 break; 27662 27663 case BinaryOperator.Divide: 27664 opStr = '/'; 27665 break; 27666 27667 case BinaryOperator.Multiply: 27668 opStr = '*'; 27669 break; 27670 27671 case BinaryOperator.Modulo: 27672 opStr = '%'; 27673 break; 27674 27675 case BinaryOperator.Lower: 27676 opStr = '<'; 27677 break; 27678 27679 case BinaryOperator.LowerEquals: 27680 opStr = '<='; 27681 break; 27682 27683 case BinaryOperator.Bigger: 27684 opStr = '>'; 27685 break; 27686 27687 case BinaryOperator.BiggerEquals: 27688 opStr = '>='; 27689 break; 27690 27691 case BinaryOperator.NullishCoalesce: 27692 opStr = '??'; 27693 break; 27694 27695 default: 27696 throw new Error(`Unknown operator ${ast.operator}`); 27697 } 27698 27699 if (ast.parens) ctx.print(ast, `(`); 27700 ast.lhs.visitExpression(this, ctx); 27701 ctx.print(ast, ` ${opStr} `); 27702 ast.rhs.visitExpression(this, ctx); 27703 if (ast.parens) ctx.print(ast, `)`); 27704 return null; 27705 } 27706 27707 visitReadPropExpr(ast, ctx) { 27708 ast.receiver.visitExpression(this, ctx); 27709 ctx.print(ast, `.`); 27710 ctx.print(ast, ast.name); 27711 return null; 27712 } 27713 27714 visitReadKeyExpr(ast, ctx) { 27715 ast.receiver.visitExpression(this, ctx); 27716 ctx.print(ast, `[`); 27717 ast.index.visitExpression(this, ctx); 27718 ctx.print(ast, `]`); 27719 return null; 27720 } 27721 27722 visitLiteralArrayExpr(ast, ctx) { 27723 ctx.print(ast, `[`); 27724 this.visitAllExpressions(ast.entries, ctx, ','); 27725 ctx.print(ast, `]`); 27726 return null; 27727 } 27728 27729 visitLiteralMapExpr(ast, ctx) { 27730 ctx.print(ast, `{`); 27731 this.visitAllObjects(entry => { 27732 ctx.print(ast, `${escapeIdentifier(entry.key, this._escapeDollarInStrings, entry.quoted)}:`); 27733 entry.value.visitExpression(this, ctx); 27734 }, ast.entries, ctx, ','); 27735 ctx.print(ast, `}`); 27736 return null; 27737 } 27738 27739 visitCommaExpr(ast, ctx) { 27740 ctx.print(ast, '('); 27741 this.visitAllExpressions(ast.parts, ctx, ','); 27742 ctx.print(ast, ')'); 27743 return null; 27744 } 27745 27746 visitAllExpressions(expressions, ctx, separator) { 27747 this.visitAllObjects(expr => expr.visitExpression(this, ctx), expressions, ctx, separator); 27748 } 27749 27750 visitAllObjects(handler, expressions, ctx, separator) { 27751 let incrementedIndent = false;
27752 27753 for (let i = 0; i < expressions.length; i++) { 27754 if (i > 0) { 27755 if (ctx.lineLength() > 80) { 27756 ctx.print(null, separator, true); 27757 27758 if (!incrementedIndent) { 27759 // continuation are marked with double indent. 27760 ctx.incIndent(); 27761 ctx.incIndent(); 27762 incrementedIndent = true; 27763 } 27764 } else { 27765 ctx.print(null, separator, false); 27766 } 27767 } 27768 27769 handler(expressions[i]); 27770 } 27771 27772 if (incrementedIndent) { 27773 // continuation are marked with double indent. 27774 ctx.decIndent(); 27775 ctx.decIndent(); 27776 } 27777 } 27778 27779 visitAllStatements(statements, ctx) { 27780 statements.forEach(stmt => stmt.visitStatement(this, ctx)); 27781 } 27782 27783} 27784 27785function escapeIdentifier(input, escapeDollar, alwaysQuote = true) { 27786 if (input == null) { 27787 return null; 27788 } 27789 27790 const body = input.replace(_SINGLE_QUOTE_ESCAPE_STRING_RE, (...match) => { 27791 if (match[0] == '$') { 27792 return escapeDollar ? '\\$' : '$'; 27793 } else if (match[0] == '\n') { 27794 return '\\n'; 27795 } else if (match[0] == '\r') { 27796 return '\\r'; 27797 } else { 27798 return `\\${match[0]}`; 27799 } 27800 }); 27801 const requiresQuotes = alwaysQuote || !_LEGAL_IDENTIFIER_RE.test(body); 27802 return requiresQuotes ? `'${body}'` : body; 27803} 27804 27805function _createIndent(count) { 27806 let res = ''; 27807 27808 for (let i = 0; i < count; i++) { 27809 res += _INDENT_WITH; 27810 } 27811 27812 return res; 27813} 27814/** 27815 * @license 27816 * Copyright Google LLC All Rights Reserved. 27817 * 27818 * Use of this source code is governed by an MIT-style license that can be 27819 * found in the LICENSE file at https://angular.io/license 27820 */ 27821 27822 27823function typeWithParameters(type, numParams) { 27824 if (numParams === 0) { 27825 return expressionType(type); 27826 } 27827 27828 const params = []; 27829 27830 for (let i = 0; i < numParams; i++) { 27831 params.push(DYNAMIC_TYPE); 27832 } 27833 27834 return expressionType(type, undefined, params); 27835} 27836 27837const ANIMATE_SYMBOL_PREFIX = '@'; 27838 27839function prepareSyntheticPropertyName(name) { 27840 return `${ANIMATE_SYMBOL_PREFIX}${name}`; 27841} 27842 27843function prepareSyntheticListenerName(name, phase) { 27844 return `${ANIMATE_SYMBOL_PREFIX}${name}.${phase}`; 27845} 27846 27847function getSafePropertyAccessString(accessor, name) { 27848 const escapedName = escapeIdentifier(name, false, false); 27849 return escapedName !== name ? `${accessor}[${escapedName}]` : `${accessor}.${name}`; 27850} 27851 27852function prepareSyntheticListenerFunctionName(name, phase) { 27853 return `animation_${name}_${phase}`; 27854} 27855 27856function jitOnlyGuardedExpression(expr) { 27857 return guardedExpression('ngJitMode', expr); 27858} 27859 27860function devOnlyGuardedExpression(expr) { 27861 return guardedExpression('ngDevMode', expr); 27862} 27863 27864function guardedExpression(guard, expr) { 27865 const guardExpr = new ExternalExpr({ 27866 name: guard, 27867 moduleName: null 27868 }); 27869 const guardNotDefined = new BinaryOperatorExpr(BinaryOperator.Identical, new TypeofExpr(guardExpr), literal('undefined')); 27870 const guardUndefinedOrTrue = new BinaryOperatorExpr(BinaryOperator.Or, guardNotDefined, guardExpr, 27871 /* type */ 27872 undefined, 27873 /* sourceSpan */ 27874 undefined, true); 27875 return new BinaryOperatorExpr(BinaryOperator.And, guardUndefinedOrTrue, expr); 27876} 27877 27878function wrapReference(value) { 27879 const wrapped = new WrappedNodeExpr(value); 27880 return { 27881 value: wrapped, 27882 type: wrapped 27883 }; 27884} 27885 27886function refsToArray(refs, shouldForwardDeclare) { 27887 const values = literalArr(refs.map(ref => ref.value));
27888 return shouldForwardDeclare ? fn([], [new ReturnStatement(values)]) : values; 27889} 27890 27891function createMayBeForwardRefExpression(expression, forwardRef) { 27892 return { 27893 expression, 27894 forwardRef 27895 }; 27896} 27897/** 27898 * Convert a `MaybeForwardRefExpression` to an `Expression`, possibly wrapping its expression in a 27899 * `forwardRef()` call. 27900 * 27901 * If `MaybeForwardRefExpression.forwardRef` is `ForwardRefHandling.Unwrapped` then the expression 27902 * was originally wrapped in a `forwardRef()` call to prevent the value from being eagerly evaluated 27903 * in the code. 27904 * 27905 * See `packages/compiler-cli/src/ngtsc/annotations/src/injectable.ts` and 27906 * `packages/compiler/src/jit_compiler_facade.ts` for more information. 27907 */ 27908 27909 27910function convertFromMaybeForwardRefExpression({ 27911 expression, 27912 forwardRef 27913}) { 27914 switch (forwardRef) { 27915 case 0 27916 /* ForwardRefHandling.None */ 27917 : 27918 case 1 27919 /* ForwardRefHandling.Wrapped */ 27920 : 27921 return expression; 27922 27923 case 2 27924 /* ForwardRefHandling.Unwrapped */ 27925 : 27926 return generateForwardRef(expression); 27927 } 27928} 27929/** 27930 * Generate an expression that has the given `expr` wrapped in the following form: 27931 * 27932 * ``` 27933 * forwardRef(() => expr) 27934 * ``` 27935 */ 27936 27937 27938function generateForwardRef(expr) { 27939 return importExpr(Identifiers.forwardRef).callFn([fn([], [new ReturnStatement
27939(expr)])]); 27940} 27941 27942var R3FactoryDelegateType; 27943 27944(function (R3FactoryDelegateType) { 27945 R3FactoryDelegateType[R3FactoryDelegateType["Class"] = 0] = "Class"; 27946 R3FactoryDelegateType[R3FactoryDelegateType["Function"] = 1] = "Function"; 27947})(R3FactoryDelegateType || (R3FactoryDelegateType = {})); 27948 27949var FactoryTarget$1; 27950 27951(function (FactoryTarget) { 27952 FactoryTarget[FactoryTarget["Directive"] = 0] = "Directive"; 27953 FactoryTarget[FactoryTarget["Component"] = 1] = "Component"; 27954 FactoryTarget[FactoryTarget["Injectable"] = 2] = "Injectable"; 27955 FactoryTarget[FactoryTarget["Pipe"] = 3] = "Pipe"; 27956 FactoryTarget[FactoryTarget["NgModule"] = 4] = "NgModule"; 27957})(FactoryTarget$1 || (FactoryTarget$1 = {})); 27958/** 27959 * Construct a factory function expression for the given `R3FactoryMetadata`. 27960 */ 27961 27962 27963function compileFactoryFunction(meta) { 27964 const t = variable('t'); 27965 let baseFactoryVar = null; // The type to instantiate via constructor invocation. If there is no delegated factory, meaning 27966 // this type is always created by constructor invocation, then this is the type-to-create 27967 // parameter provided by the user (t) if specified, or the current type if not. If there is a 27968 // delegated factory (which is used to create the current type) then this is only the type-to- 27969 // create parameter (t). 27970 27971 const typeForCtor = !isDelegatedFactoryMetadata(meta) ? new BinaryOperatorExpr(BinaryOperator.Or, t, meta.internalType) : t; 27972 let ctorExpr = null; 27973 27974 if (meta.deps !== null) { 27975 // There is a constructor (either explicitly or implicitly defined). 27976 if (meta.deps !== 'invalid') { 27977 ctorExpr = new InstantiateExpr(typeForCtor, injectDependencies(meta.deps, meta.target)); 27978 } 27979 } else { 27980 // There is no constructor, use the base class' factory to construct typeForCtor. 27981 baseFactoryVar = variable(`ɵ${meta.name}_BaseFactory`); 27982 ctorExpr = baseFactoryVar.callFn([typeForCtor]); 27983 } 27984 27985 const body = []; 27986 let retExpr = null; 27987 27988 function makeConditionalFactory(nonCtorExpr) { 27989 const r = variable('r'); 27990 body.push(r.set(NULL_EXPR).toDeclStmt()); 27991 const ctorStmt = ctorExpr !== null ? r.set(ctorExpr).toStmt() : importExpr(Identifiers.invalidFactory).callFn([]).toStmt(); 27992 body.push(ifStmt(t, [ctorStmt], [r.set(nonCtorExpr).toStmt()])); 27993 return r; 27994 } 27995 27996 if (isDelegatedFactoryMetadata(meta)) { 27997 // This type is created with a delegated factory. If a type parameter is not specified, call 27998 // the factory instead. 27999 const delegateArgs = injectDependencies(meta.delegateDeps, meta.target); // Either call `new delegate(...)` or `delegate(...)` depending on meta.delegateType. 28000 28001 const factoryExpr = new (meta.delegateType === R3FactoryDelegateType.Class ? InstantiateExpr : InvokeFunctionExpr)(meta.delegate, delegateArgs); 28002 retExpr = makeConditionalFactory(factoryExpr); 28003 } else if (isExpressionFactoryMetadata(meta)) { 28004 // TODO(alxhub): decide whether to lower the value here or in the caller 28005 retExpr = makeConditionalFactory(meta.expression); 28006 } else { 28007 retExpr = ctorExpr; 28008 } 28009 28010 if (retExpr === null) { 28011 // The expression cannot be formed so render an `ɵɵinvalidFactory()` call. 28012 body.push(importExpr(Identifiers.invalidFactory).callFn([]).toStmt()); 28013 } else if (baseFactoryVar !== null) { 28014 // This factory uses a base factory, so call `ɵɵgetInheritedFactory()` to compute it. 28015 const getInheritedFactoryCall = importExpr(Identifiers.getInheritedFactory).callFn([meta.internalType]); // Memoize the base factoryFn: `baseFactory || (baseFactory = ɵɵgetInheritedFactory(...))` 28016 28017 const baseFactory = new BinaryOperatorExpr(BinaryOperator.Or, baseFactoryVar, baseFactoryVar.set(getInheritedFactoryCall));
28018 body.push(new ReturnStatement(baseFactory.callFn([typeForCtor]))); 28019 } else { 28020 // This is straightforward factory, just return it. 28021 body.push(new ReturnStatement(retExpr)); 28022 } 28023 28024 let factoryFn = fn([new FnParam('t', DYNAMIC_TYPE)], body, INFERRED_TYPE, undefined, `${meta.name}_Factory`); 28025 28026 if (baseFactoryVar !== null) { 28027 // There is a base factory variable so wrap its declaration along with the factory function into 28028 // an IIFE. 28029 factoryFn = fn([], [new DeclareVarStmt(baseFactoryVar.name), new ReturnStatement(factoryFn)]).callFn([], 28030 /* sourceSpan */ 28031 undefined, 28032 /* pure */ 28033 true); 28034 } 28035 28036 return { 28037 expression: factoryFn, 28038 statements: [], 28039 type: createFactoryType(meta) 28040 }; 28041} 28042 28043function createFactoryType(meta) { 28044 const ctorDepsType = meta.deps !== null && meta.deps !== 'invalid' ? createCtorDepsType(meta.deps) : NONE_TYPE; 28045 return expressionType(importExpr(Identifiers.FactoryDeclaration, [typeWithParameters(meta.type.type, meta.typeArgumentCount), ctorDepsType])); 28046} 28047 28048function injectDependencies(deps, target) { 28049 return deps.map((dep, index) => compileInjectDependency(dep, target, index)); 28050} 28051 28052function compileInjectDependency(dep, target, index) { 28053 // Interpret the dependency according to its resolved type. 28054 if (dep.token === null) { 28055 return importExpr(Identifiers.invalidFactoryDep).callFn([literal(index)]); 28056 } else if (dep.attributeNameType === null) { 28057 // Build up the injection flags according to the metadata. 28058 const flags = 0 28059 /* InjectFlags.Default */ 28060 | (dep.self ? 2 28061 /* InjectFlags.Self */ 28062 : 0) | (dep.skipSelf ? 4 28063 /* InjectFlags.SkipSelf */ 28064 : 0) | (dep.host ? 1 28065 /* InjectFlags.Host */ 28066 : 0) | (dep.optional ? 8 28067 /* InjectFlags.Optional */ 28068 : 0) | (target === FactoryTarget$1.Pipe ? 16 28069 /* InjectFlags.ForPipe */ 28070 : 0); // If this dependency is optional or otherwise has non-default flags, then additional 28071 // parameters describing how to inject the dependency must be passed to the inject function 28072 // that's being used. 28073 28074 let flagsParam = flags !== 0 28075 /* InjectFlags.Default */ 28076 || dep.optional ? literal(flags) : null; // Build up the arguments to the injectFn call. 28077 28078 const injectArgs = [dep.token]; 28079 28080 if (flagsParam) { 28081 injectArgs.push(flagsParam); 28082 } 28083 28084 const injectFn = getInjectFn(target); 28085 return importExpr(injectFn).callFn(injectArgs); 28086 } else { 28087 // The `dep.attributeTypeName` value is defined, which indicates that this is an `@Attribute()` 28088 // type dependency. For the generated JS we still want to use the `dep.token` value in case the 28089 // name given for the attribute is not a string literal. For example given `@Attribute(foo())`, 28090 // we want to generate `ɵɵinjectAttribute(foo())`. 28091 // 28092 // The `dep.attributeTypeName` is only actually used (in `createCtorDepType()`) to generate 28093 // typings. 28094 return importExpr(Identifiers.injectAttribute).callFn([dep.token]); 28095 } 28096} 28097 28098function createCtorDepsType(deps) { 28099 let hasTypes = false; 28100 const attributeTypes = deps.map(dep => { 28101 const type = createCtorDepType(dep); 28102 28103 if (type !== null) { 28104 hasTypes = true; 28105 return type; 28106 } else { 28107 return literal(null); 28108 } 28109 }); 28110 28111 if (hasTypes) { 28112 return expressionType(literalArr(attributeTypes)); 28113 } else { 28114 return NONE_TYPE; 28115 } 28116} 28117 28118function createCtorDepType(dep) { 28119 const entries = []; 28120 28121 if (dep.attributeNameType !== null) { 28122 entries.push({ 28123 key: 'attribute', 28124 value: dep.attributeNameType, 28125 quoted: false 28126 }); 28127 } 28128 28129 if (dep.optional) { 28130 entries.push({ 28131 key: 'optional', 28132 value: literal(true), 28133 quoted: false 28134 }); 28135 } 28136 28137 if (dep.host) { 28138 entries.push({ 28139 key: 'host', 28140 value: literal(true), 28141 quoted: false 28142 }); 28143 } 28144 28145 if (dep.self) { 28146 entries.push({ 28147 key: 'self', 28148 value: literal(true), 28149 quoted: false 28150 }); 28151 } 28152 28153 if (dep.skipSelf) { 28154 entries.push({ 28155 key: 'skipSelf', 28156 value: literal(true), 28157 quoted: false 28158 }); 28159 } 28160 28161 return entries.length > 0 ? literalMap(entries) : null; 28162} 28163 28164function isDelegatedFactoryMetadata(meta) { 28165 return meta.delegateType !== undefined; 28166} 28167 28168function isExpressionFactoryMetadata(meta) { 28169 return meta.expression !== undefined; 28170} 28171 28172function getInjectFn(target) { 28173 switch (target) { 28174 case FactoryTarget$1.Component: 28175 case FactoryTarget$1.Directive: 28176 case FactoryTarget$1.Pipe: 28177 return Identifiers.directiveInject; 28178 28179 case FactoryTarget$1.NgModule: 28180 case FactoryTarget$1.Injectable: 28181 default: 28182 return Identifiers.inject; 28183 } 28184} 28185/** 28186 * @license 28187 * Copyright Google LLC All Rights Reserved. 28188 * 28189 * Use of this source code is governed by an MIT-style license that can be 28190 * found in the LICENSE file at https://angular.io/license 28191 */ 28192 28193/** 28194 * This is an R3 `Node`-like wrapper for a raw `html.Comment` node. We do not currently 28195 * require the implementation of a visitor for Comments as they are only collected at 28196 * the top-level of the R3 AST, and only if `Render3ParseOptions['collectCommentNodes']` 28197 * is true. 28198 */ 28199 28200 28201class Comment$1 { 28202 constructor(value, sourceSpan) { 28203 this.value = value; 28204 this.sourceSpan = sourceSpan; 28205 } 28206 28207 visit(_visitor) { 28208 throw new Error('visit() not implemented for Comment'); 28209 } 28210 28211} 28212 28213class Text$3 { 28214 constructor(value, sourceSpan) { 28215 this.value = value; 28216 this.sourceSpan = sourceSpan; 28217 } 28218 28219 visit(visitor) { 28220 return visitor.visitText(this); 28221 } 28222 28223} 28224 28225class BoundText { 28226 constructor(value, sourceSpan, i18n) { 28227 this.value = value; 28228 this.sourceSpan = sourceSpan; 28229 this.i18n = i18n; 28230 } 28231 28232 visit(visitor) { 28233 return visitor.visitBoundText(this); 28234 } 28235 28236} 28237/** 28238 * Represents a text attribute in the template. 28239 * 28240 * `valueSpan` may not be present in cases where there is no value `<div a></div>`. 28241 * `keySpan` may also not be present for synthetic attributes from ICU expansions. 28242 */ 28243 28244 28245class TextAttribute { 28246 constructor(name, value, sourceSpan, keySpan, valueSpan, i18n) { 28247 this.name = name; 28248 this.value = value; 28249 this.sourceSpan = sourceSpan; 28250 this.keySpan = keySpan; 28251 this.valueSpan = valueSpan; 28252 this.i18n = i18n; 28253 } 28254 28255 visit(visitor) { 28256 return visitor.visitTextAttribute(this); 28257 } 28258 28259} 28260 28261class BoundAttribute { 28262 constructor(name, type, securityContext, value, unit, sourceSpan, keySpan, valueSpan, i18n) { 28263 this.name = name; 28264 this.type = type; 28265 this.securityContext = securityContext; 28266 this.value = value; 28267 this.unit = unit; 28268 this.sourceSpan = sourceSpan; 28269 this.keySpan = keySpan; 28270 this.valueSpan = valueSpan; 28271 this.i18n = i18n; 28272 } 28273 28274 static fromBoundElementProperty(prop, i18n) {
28275 if (prop.keySpan === undefined) { 28276 throw new Error(`Unexpected state: keySpan must be defined for bound attributes but was not for ${prop.name}: ${prop.sourceSpan}`); 28277 } 28278 28279 return new BoundAttribute(prop.name, prop.type, prop.securityContext, prop.value, prop.unit, prop.sourceSpan, prop.keySpan, prop.valueSpan, i18n); 28280 } 28281 28282 visit(visitor) { 28283 return visitor.visitBoundAttribute(this); 28284 } 28285 28286} 28287 28288class BoundEvent { 28289 constructor(name, type, handler, target, phase, sourceSpan, handlerSpan, keySpan) { 28290 this.name = name; 28291 this.type = type; 28292 this.handler = handler; 28293 this.target = target; 28294 this.phase = phase; 28295 this.sourceSpan = sourceSpan; 28296 this.handlerSpan = handlerSpan; 28297 this.keySpan = keySpan; 28298 } 28299 28300 static fromParsedEvent(event) { 28301 const target = event.type === 0 28302 /* ParsedEventType.Regular */ 28303 ? event.targetOrPhase : null; 28304 const phase = event.type === 1 28305 /* ParsedEventType.Animation */ 28306 ? event.targetOrPhase : null; 28307 28308 if (event.keySpan === undefined) { 28309 throw new Error(`Unexpected state: keySpan must be defined for bound event but was not for ${event.name}: ${event.sourceSpan}`); 28310 } 28311 28312 return new BoundEvent(event.name, event.type, event.handler, target, phase, event.sourceSpan, event.handlerSpan, event.keySpan); 28313 } 28314 28315 visit(visitor) { 28316 return visitor.visitBoundEvent(this); 28317 } 28318 28319} 28320 28321class Element$1 { 28322 constructor(name, attributes, inputs, outputs, children, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) { 28323 this.name = name; 28324 this.attributes = attributes; 28325 this.inputs = inputs; 28326 this.outputs = outputs; 28327 this.children = children; 28328 this.references = references; 28329 this.sourceSpan = sourceSpan; 28330 this.startSourceSpan = startSourceSpan; 28331 this.endSourceSpan = endSourceSpan; 28332 this.i18n = i18n; 28333 } 28334 28335 visit(visitor) { 28336 return visitor.visitElement(this); 28337 } 28338 28339} 28340 28341class Template { 28342 constructor( // tagName is the name of the container element, if applicable. 28343 // `null` is a special case for when there is a structural directive on an `ng-template` so 28344 // the renderer can differentiate between the synthetic template and the one written in the 28345 // file. 28346 tagName, attributes, inputs, outputs, templateAttrs, children, references, variables, sourceSpan, startSourceSpan, endSourceSpan, i18n) { 28347 this.tagName = tagName; 28348 this.attributes = attributes; 28349 this.inputs = inputs; 28350 this.outputs = outputs; 28351 this.templateAttrs = templateAttrs; 28352 this.children = children; 28353 this.references = references; 28354 this.variables = variables; 28355 this.sourceSpan = sourceSpan; 28356 this.startSourceSpan = startSourceSpan; 28357 this.endSourceSpan = endSourceSpan; 28358 this.i18n = i18n; 28359 } 28360 28361 visit(visitor) { 28362 return visitor.visitTemplate(this); 28363 } 28364 28365} 28366 28367class Content { 28368 constructor(selector, attributes, sourceSpan, i18n) { 28369 this.selector = selector; 28370 this.attributes = attributes; 28371 this.sourceSpan = sourceSpan; 28372 this.i18n = i18n; 28373 this.name = 'ng-content'; 28374 } 28375 28376 visit(visitor) { 28377 return visitor.visitContent(this); 28378 } 28379 28380} 28381 28382class Variable { 28383 constructor(name, value, sourceSpan, keySpan, valueSpan) { 28384 this.name = name; 28385 this.value = value; 28386 this.sourceSpan = sourceSpan; 28387 this.keySpan = keySpan; 28388 this.valueSpan = valueSpan; 28389 } 28390 28391 visit(visitor) { 28392 return visitor.visitVariable(this); 28393 } 28394 28395} 28396 28397class Reference { 28398 constructor(name, value, sourceSpan, keySpan, valueSpan) { 28399 this.name = name; 28400 this.value = value; 28401 this.sourceSpan = sourceSpan; 28402 this.keySpan = keySpan; 28403 this.valueSpan = valueSpan; 28404 } 28405 28406 visit(visitor) { 28407 return visitor.visitReference(this); 28408 } 28409 28410} 28411 28412class Icu$1 { 28413 constructor(vars, placeholders, sourceSpan, i18n) { 28414 this.vars = vars; 28415 this.placeholders = placeholders; 28416 this.sourceSpan = sourceSpan; 28417 this.i18n = i18n; 28418 } 28419 28420 visit(visitor) { 28421 return visitor.visitIcu(this); 28422 } 28423 28424} 28425 28426class NullVisitor { 28427 visitElement(element) {} 28428 28429 visitTemplate(template) {} 28430 28431 visitContent(content) {} 28432 28433 visitVariable(variable) {} 28434 28435 visitReference(reference) {} 28436 28437 visitTextAttribute(attribute) {} 28438 28439 visitBoundAttribute(attribute) {} 28440 28441 visitBoundEvent(attribute) {} 28442 28443 visitText(text) {} 28444 28445 visitBoundText(text) {} 28446 28447 visitIcu(icu) {} 28448 28449} 28450 28451class RecursiveVisitor$1 { 28452 visitElement(element) { 28453 visitAll$1(this, element.attributes); 28454 visitAll$1(this, element.inputs); 28455 visitAll$1(this, element.outputs); 28456 visitAll$1(this, element.children); 28457 visitAll$1(this, element.references); 28458 } 28459 28460 visitTemplate(template) { 28461 visitAll$1(this, template.attributes); 28462 visitAll$1(this, template.inputs); 28463 visitAll$1(this, template.outputs); 28464 visitAll$1(this, template.children); 28465 visitAll$1(this, template.references); 28466 visitAll$1(this, template.variables); 28467 } 28468 28469 visitContent(content) {} 28470 28471 visitVariable(variable) {} 28472 28473 visitReference(reference) {} 28474 28475 visitTextAttribute(attribute) {} 28476 28477 visitBoundAttribute(attribute) {} 28478 28479 visitBoundEvent(attribute) {} 28480 28481 visitText(text) {} 28482 28483 visitBoundText(text) {} 28484 28485 visitIcu(icu) {} 28486 28487} 28488 28489class TransformVisitor { 28490 visitElement(element) { 28491 const newAttributes = transformAll(this, element.attributes);
28492 const newInputs = transformAll(this, element.inputs); 28493 const newOutputs = transformAll(this, element.outputs); 28494 const newChildren = transformAll(this, element.children); 28495 const newReferences = transformAll(this, element.references); 28496 28497 if (newAttributes != element.attributes || newInputs != element.inputs || newOutputs != element.outputs || newChildren != element.children || newReferences != element.references) { 28498 return new Element$1(element.name, newAttributes, newInputs, newOutputs, newChildren, newReferences, element.sourceSpan, element.startSourceSpan, element.endSourceSpan); 28499 } 28500 28501 return element; 28502 } 28503 28504 visitTemplate(template) { 28505 const newAttributes = transformAll(this, template.attributes); 28506 const newInputs = transformAll(this, template.inputs); 28507 const newOutputs = transformAll(this, template.outputs); 28508 const newTemplateAttrs = transformAll(this, template.templateAttrs); 28509 const newChildren = transformAll(this, template.children); 28510 const newReferences = transformAll(this, template.references); 28511 const newVariables = transformAll(this, template.variables); 28512 28513 if (newAttributes != template.attributes || newInputs != template.inputs || newOutputs != template.outputs || newTemplateAttrs != template.templateAttrs || newChildren != template.children || newReferences != template.references || newVariables != template.variables) { 28514 return new Template(template.tagName, newAttributes, newInputs, newOutputs, newTemplateAttrs, newChildren, newReferences, newVariables, template.sourceSpan, template.startSourceSpan, template.endSourceSpan); 28515 } 28516 28517 return template; 28518 } 28519 28520 visitContent(content) { 28521 return content; 28522 } 28523 28524 visitVariable(variable) { 28525 return variable; 28526 } 28527 28528 visitReference(reference) { 28529 return reference; 28530 } 28531 28532 visitTextAttribute(attribute) { 28533 return attribute; 28534 } 28535 28536 visitBoundAttribute(attribute) { 28537 return attribute; 28538 } 28539 28540 visitBoundEvent(attribute) { 28541 return attribute; 28542 } 28543 28544 visitText(text) { 28545 return text; 28546 } 28547 28548 visitBoundText(text) { 28549 return text; 28550 } 28551 28552 visitIcu(icu) { 28553 return icu; 28554 } 28555 28556} 28557 28558function visitAll$1(visitor, nodes) { 28559 const result = []; 28560 28561 if (visitor.visit) { 28562 for (const node of nodes) { 28563 const newNode = visitor.visit(node) || node.visit(visitor); 28564 } 28565 } else { 28566 for (const node of nodes) { 28567 const newNode = node.visit(visitor); 28568 28569 if (newNode) { 28570 result.push(newNode); 28571 } 28572 } 28573 } 28574 28575 return result; 28576} 28577 28578function transformAll(visitor, nodes) { 28579 const result = []; 28580 let changed = false; 28581 28582 for (const node of nodes) { 28583 const newNode = node.visit(visitor); 28584 28585 if (newNode) { 28586 result.push(newNode); 28587 } 28588 28589 changed = changed || newNode != node; 28590 } 28591 28592 return changed ? result : nodes; 28593} 28594/** 28595 * @license 28596 * Copyright Google LLC All Rights Reserved. 28597 * 28598 * Use of this source code is governed by an MIT-style license that can be 28599 * found in the LICENSE file at https://angular.io/license 28600 */ 28601 28602 28603class Message { 28604 /** 28605 * @param nodes message AST 28606 * @param placeholders maps placeholder names to static content and their source spans 28607 * @param placeholderToMessage maps placeholder names to messages (used for nested ICU messages) 28608 * @param meaning 28609 * @param description 28610 * @param customId 28611 */ 28612 constructor(nodes, placeholders, placeholderToMessage, meaning, description, customId) { 28613 this.nodes = nodes; 28614 this.placeholders = placeholders; 28615 this.placeholderToMessage = placeholderToMessage; 28616 this.meaning = meaning; 28617 this.description = description; 28618 this.customId = customId; 28619 this.id = this.customId; 28620 /** The ids to use if there are no custom id and if `i18nLegacyMessageIdFormat` is not empty */ 28621 28622 this.legacyIds = []; 28623 this.messageString = serializeMessage(this.nodes); 28624 28625 if (nodes.length) { 28626 this.sources = [{ 28627 filePath: nodes[0].sourceSpan.start.file.url, 28628 startLine: nodes[0].sourceSpan.start.line + 1, 28629 startCol: nodes[0].sourceSpan.start.col + 1, 28630 endLine: nodes[nodes.length - 1].sourceSpan.end.line + 1, 28631 endCol: nodes[0].sourceSpan.start.col + 1 28632 }]; 28633 } else { 28634 this.sources = []; 28635 } 28636 } 28637 28638} 28639 28640class Text$2 { 28641 constructor(value, sourceSpan) { 28642 this.value = value; 28643 this.sourceSpan = sourceSpan; 28644 } 28645 28646 visit(visitor, context) { 28647 return visitor.visitText(this, context); 28648 } 28649 28650} // TODO(vicb): do we really need this node (vs an array) ? 28651 28652 28653class Container { 28654 constructor(children, sourceSpan) { 28655 this.children = children; 28656 this.sourceSpan = sourceSpan; 28657 } 28658 28659 visit(visitor, context) { 28660 return visitor.visitContainer(this, context); 28661 } 28662 28663} 28664 28665class Icu { 28666 constructor(expression, type, cases, sourceSpan) { 28667 this.expression = expression; 28668 this.type = type; 28669 this.cases = cases; 28670 this.sourceSpan = sourceSpan; 28671 } 28672 28673 visit(visitor, context) { 28674 return visitor.visitIcu(this, context); 28675 } 28676 28677} 28678 28679class TagPlaceholder { 28680 constructor(tag, attrs, startName, closeName, children, isVoid, // TODO sourceSpan should cover all (we need a startSourceSpan and endSourceSpan) 28681 sourceSpan, startSourceSpan, endSourceSpan) { 28682 this.tag = tag; 28683 this.attrs = attrs; 28684 this.startName = startName; 28685 this.closeName = closeName; 28686 this.children = children; 28687 this.isVoid = isVoid; 28688 this.sourceSpan = sourceSpan; 28689 this.startSourceSpan = startSourceSpan; 28690 this.endSourceSpan = endSourceSpan; 28691 } 28692 28693 visit(visitor, context) { 28694 return visitor.visitTagPlaceholder(this, context); 28695 } 28696 28697} 28698 28699class Placeholder { 28700 constructor(value, name, sourceSpan) { 28701 this.value = value; 28702 this.name = name; 28703 this.sourceSpan = sourceSpan; 28704 } 28705 28706 visit(visitor, context) { 28707 return visitor.visitPlaceholder(this, context); 28708 } 28709 28710} 28711 28712class IcuPlaceholder { 28713 constructor(value, name, sourceSpan) { 28714 this.value = value; 28715 this.name = name; 28716 this.sourceSpan = sourceSpan; 28717 } 28718 28719 visit(visitor, context) { 28720 return visitor.visitIcuPlaceholder(this, context); 28721 } 28722 28723} // Clone the AST 28724 28725 28726class CloneVisitor { 28727 visitText(text, context) { 28728 return new Text$2(text.value, text.sourceSpan); 28729 } 28730 28731 visitContainer(container, context) { 28732 const children = container.children.map(n => n.visit(this, context)); 28733 return new Container(children, container.sourceSpan); 28734 } 28735 28736 visitIcu(icu, context) { 28737 const cases = {};
28738 Object.keys(icu.cases).forEach(key => cases[key] = icu.cases[key].visit(this, context)); 28739 const msg = new Icu(icu.expression, icu.type, cases, icu.sourceSpan); 28740 msg.expressionPlaceholder = icu.expressionPlaceholder; 28741 return msg; 28742 } 28743 28744 visitTagPlaceholder(ph, context) { 28745 const children = ph.children.map(n => n.visit(this, context)); 28746 return new TagPlaceholder(ph.tag, ph.attrs, ph.startName, ph.closeName, children, ph.isVoid, ph.sourceSpan, ph.startSourceSpan, ph.endSourceSpan); 28747 } 28748 28749 visitPlaceholder(ph, context) { 28750 return new Placeholder(ph.value, ph.name, ph.sourceSpan); 28751 } 28752 28753 visitIcuPlaceholder(ph, context) { 28754 return new IcuPlaceholder(ph.value, ph.name, ph.sourceSpan); 28755 } 28756 28757} // Visit all the nodes recursively 28758 28759 28760class RecurseVisitor { 28761 visitText(text, context) {} 28762 28763 visitContainer(container, context) { 28764 container.children.forEach(child => child.visit(this)); 28765 } 28766 28767 visitIcu(icu, context) { 28768 Object.keys(icu.cases).forEach(k => { 28769 icu.cases[k].visit(this); 28770 }); 28771 } 28772 28773 visitTagPlaceholder(ph, context) { 28774 ph.children.forEach(child => child.visit(this)); 28775 } 28776 28777 visitPlaceholder(ph, context) {} 28778 28779 visitIcuPlaceholder(ph, context) {} 28780 28781} 28782/** 28783 * Serialize the message to the Localize backtick string format that would appear in compiled code. 28784 */ 28785 28786 28787function serializeMessage(messageNodes) { 28788 const visitor = new LocalizeMessageStringVisitor(); 28789 const str = messageNodes.map(n => n.visit(visitor)).join(''); 28790 return str; 28791} 28792 28793class LocalizeMessageStringVisitor { 28794 visitText(text) { 28795 return text.value; 28796 } 28797 28798 visitContainer(container) { 28799 return container.children.map(child => child.visit(this)).join(''); 28800 } 28801 28802 visitIcu(icu) { 28803 const strCases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`); 28804 return `{${icu.expressionPlaceholder}, ${icu.type}, ${strCases.join(' ')}}`; 28805 } 28806 28807 visitTagPlaceholder(ph) { 28808 const children = ph.children.map(child => child.visit(this)).join(''); 28809 return `{$${ph.startName}}${children}{$${ph.closeName}}`; 28810 } 28811 28812 visitPlaceholder(ph) { 28813 return `{$${ph.name}}`; 28814 } 28815 28816 visitIcuPlaceholder(ph) { 28817 return `{$${ph.name}}`; 28818 } 28819 28820} 28821/** 28822 * @license 28823 * Copyright Google LLC All Rights Reserved. 28824 * 28825 * Use of this source code is governed by an MIT-style license that can be 28826 * found in the LICENSE file at https://angular.io/license 28827 */ 28828 28829 28830class Serializer { 28831 // Creates a name mapper, see `PlaceholderMapper` 28832 // Returning `null` means that no name mapping is used. 28833 createNameMapper(message) { 28834 return null; 28835 } 28836 28837} 28838/** 28839 * A simple mapper that take a function to transform an internal name to a public name 28840 */ 28841 28842 28843class SimplePlaceholderMapper extends RecurseVisitor { 28844 // create a mapping from the message 28845 constructor(message, mapName) { 28846 super(); 28847 this.mapName = mapName; 28848 this.internalToPublic = {}; 28849 this.publicToNextId = {}; 28850 this.publicToInternal = {}; 28851 message.nodes.forEach(node => node.visit(this)); 28852 } 28853 28854 toPublicName(internalName) { 28855 return this.internalToPublic.hasOwnProperty(internalName) ? this.internalToPublic[internalName] : null; 28856 } 28857 28858 toInternalName(publicName) { 28859 return this.publicToInternal.hasOwnProperty(publicName) ? this.publicToInternal[publicName] : null; 28860 } 28861 28862 visitText(text, context) { 28863 return null; 28864 } 28865 28866 visitTagPlaceholder(ph, context) { 28867 this.visitPlaceholderName(ph.startName); 28868 super.visitTagPlaceholder(ph, context); 28869 this.visitPlaceholderName(ph.closeName); 28870 } 28871 28872 visitPlaceholder(ph, context) { 28873 this.visitPlaceholderName(ph.name); 28874 } 28875 28876 visitIcuPlaceholder(ph, context) { 28877 this.visitPlaceholderName(ph.name); 28878 } // XMB placeholders could only contains A-Z, 0-9 and _ 28879 28880 28881 visitPlaceholderName(internalName) { 28882 if (!internalName || this.internalToPublic.hasOwnProperty(internalName)) { 28883 return; 28884 } 28885 28886 let publicName = this.mapName(internalName); 28887 28888 if (this.publicToInternal.hasOwnProperty(publicName)) { 28889 // Create a new XMB when it has already been used 28890 const nextId = this.publicToNextId[publicName]; 28891 this.publicToNextId[publicName] = nextId + 1; 28892 publicName = `${publicName}_${nextId}`; 28893 } else { 28894 this.publicToNextId[publicName] = 1; 28895 } 28896 28897 this.internalToPublic[internalName] = publicName; 28898 this.publicToInternal[publicName] = internalName; 28899 } 28900 28901} 28902/** 28903 * @license 28904 * Copyright Google LLC All Rights Reserved. 28905 * 28906 * Use of this source code is governed by an MIT-style license that can be 28907 * found in the LICENSE file at https://angular.io/license 28908 */ 28909 28910 28911class _Visitor$2 { 28912 visitTag(tag) { 28913 const strAttrs = this._serializeAttributes(tag.attrs); 28914 28915 if (tag.children.length == 0) { 28916 return `<${tag.name}${strAttrs}/>`; 28917 } 28918 28919 const strChildren = tag.children.map(node =>
28919 node.visit(this)); 28920 return `<${tag.name}${strAttrs}>${strChildren.join('')}</${tag.name}>`; 28921 } 28922 28923 visitText(text) { 28924 return text.value; 28925 } 28926 28927 visitDeclaration(decl) { 28928 return `<?xml${this._serializeAttributes(decl.attrs)} ?>`; 28929 } 28930 28931 _serializeAttributes(attrs) { 28932 const strAttrs = Object.keys(attrs).map(name => `${name}="${attrs[name]}"`).join(' '); 28933 return strAttrs.length > 0 ? ' ' + strAttrs : ''; 28934 } 28935 28936 visitDoctype(doctype) { 28937 return `<!DOCTYPE ${doctype.rootTag} [\n${doctype.dtd}\n]>`; 28938 } 28939 28940} 28941 28942const _visitor = new _Visitor$2(); 28943 28944function serialize(nodes) { 28945 return nodes.map(node => node.visit(_visitor)).join(''); 28946} 28947 28948class Declaration { 28949 constructor(unescapedAttrs) { 28950 this.attrs = {}; 28951 Object.keys(unescapedAttrs).forEach(k => { 28952 this.attrs[k] = escapeXml(unescapedAttrs[k]); 28953 }); 28954 } 28955 28956 visit(visitor) { 28957 return visitor.visitDeclaration(this); 28958 } 28959 28960} 28961 28962class Doctype { 28963 constructor(rootTag, dtd) { 28964 this.rootTag = rootTag; 28965 this.dtd = dtd; 28966 } 28967 28968 visit(visitor) { 28969 return visitor.visitDoctype(this); 28970 } 28971 28972} 28973 28974class Tag { 28975 constructor(name, unescapedAttrs = {}, children = []) { 28976 this.name = name; 28977 this.children = children; 28978 this.attrs = {}; 28979 Object.keys(unescapedAttrs).forEach(k => { 28980 this.attrs[k] = escapeXml(unescapedAttrs[k]); 28981 }); 28982 } 28983 28984 visit(visitor) { 28985 return visitor.visitTag(this); 28986 } 28987 28988} 28989 28990class Text$1 { 28991 constructor(unescapedValue) { 28992 this.value = escapeXml(unescapedValue); 28993 } 28994 28995 visit(visitor) { 28996 return visitor.visitText(this); 28997 } 28998 28999} 29000 29001class CR extends Text$1 { 29002 constructor(ws = 0) { 29003 super(`\n${new Array(ws + 1).join(' ')}`); 29004 } 29005 29006} 29007 29008const _ESCAPED_CHARS = [[/&/g, '&'], [/"/g, '"'], [/'/g, '''], [/</g, '<'], [/>/g, '>']]; // Escape `_ESCAPED_CHARS` characters in the given text with encoded entities 29009 29010function escapeXml(text) { 29011 return _ESCAPED_CHARS.reduce((text, entry) => text.replace(entry[0], entry[1]), text); 29012} 29013/** 29014 * @license 29015 * Copyright Google LLC All Rights Reserved. 29016 * 29017 * Use of this source code is governed by an MIT-style license that can be 29018 * found in the LICENSE file at https://angular.io/license 29019 */ 29020 29021 29022const _MESSAGES_TAG = 'messagebundle'; 29023const _MESSAGE_TAG = 'msg'; 29024const _PLACEHOLDER_TAG$3 = 'ph'; 29025const _EXAMPLE_TAG = 'ex'; 29026const _SOURCE_TAG$2 = 'source'; 29027const _DOCTYPE = `<!ELEMENT messagebundle (msg)*> 29028<!ATTLIST messagebundle class CDATA #IMPLIED> 29029 29030<!ELEMENT msg (#PCDATA|ph|source)*> 29031<!ATTLIST msg id CDATA #IMPLIED> 29032<!ATTLIST msg seq CDATA #IMPLIED> 29033<!ATTLIST msg name CDATA #IMPLIED> 29034<!ATTLIST msg desc CDATA #IMPLIED> 29035<!ATTLIST msg meaning CDATA #IMPLIED> 29036<!ATTLIST msg obsolete (obsolete) #IMPLIED> 29037<!ATTLIST msg xml:space (default|preserve) "default"> 29038<!ATTLIST msg is_hidden CDATA #IMPLIED> 29039 29040<!ELEMENT source (#PCDATA)> 29041 29042<!ELEMENT ph (#PCDATA|ex)*> 29043<!ATTLIST ph name CDATA #REQUIRED> 29044 29045<!ELEMENT ex (#PCDATA)>`; 29046 29047class Xmb extends Serializer { 29048 write(messages, locale) { 29049 const exampleVisitor = new ExampleVisitor(); 29050 const visitor = new _Visitor$1(); 29051 let rootNode = new Tag(_MESSAGES_TAG); 29052 messages.forEach(message => { 29053 const attrs = { 29054 id: message.id 29055 }; 29056 29057 if (message.description) { 29058 attrs['desc'] = message.description; 29059 } 29060 29061 if (message.meaning) { 29062 attrs['meaning'] = message.meaning; 29063 } 29064 29065 let sourceTags = []; 29066 message.sources.forEach(source => { 29067 sourceTags.push(new Tag(_SOURCE_TAG$2, {}, [new Text$1(`${source.filePath}:${source.startLine}${source.endLine !== source.startLine ? ',' + source.endLine : ''}`)])); 29068 }); 29069 rootNode.children.push(new CR(2), new Tag(_MESSAGE_TAG, attrs, [...sourceTags, ...visitor.serialize(message.nodes)])); 29070 }); 29071 rootNode.children.push(new CR()); 29072 return serialize([new Declaration({ 29073 version: '1.0', 29074 encoding: 'UTF-8' 29075 }), new CR(), new Doctype(_MESSAGES_TAG, _DOCTYPE), new CR(), exampleVisitor.addDefaultExamples(rootNode), new CR()]); 29076 } 29077 29078 load(content, url) { 29079 throw new Error('Unsupported'); 29080 } 29081 29082 digest(message) { 29083 return digest(message); 29084 } 29085 29086 createNameMapper(message) { 29087 return new SimplePlaceholderMapper(message, toPublicName); 29088 } 29089 29090} 29091 29092class _Visitor$1 { 29093 visitText(text, context) { 29094 return [new Text$1(text.value)]; 29095 } 29096 29097 visitContainer(container, context) { 29098 const nodes = [];
29099 container.children.forEach(node => nodes.push(...node.visit(this))); 29100 return nodes; 29101 } 29102 29103 visitIcu(icu, context) { 29104 const nodes = [new Text$1(`{${icu.expressionPlaceholder}, ${icu.type}, `)]; 29105 Object.keys(icu.cases).forEach(c => { 29106 nodes.push(new Text$1(`${c} {`), ...icu.cases[c].visit(this), new Text$1(`} `)); 29107 }); 29108 nodes.push(new Text$1(`}`)); 29109 return nodes; 29110 } 29111 29112 visitTagPlaceholder(ph, context) { 29113 const startTagAsText = new Text$1(`<${ph.tag}>`); 29114 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. 29115 29116 const startTagPh = new Tag(_PLACEHOLDER_TAG$3, { 29117 name: ph.startName 29118 }, [startEx, startTagAsText]); 29119 29120 if (ph.isVoid) { 29121 // void tags have no children nor closing tags 29122 return [startTagPh]; 29123 } 29124 29125 const closeTagAsText = new Text$1(`</${ph.tag}>`); 29126 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. 29127 29128 const closeTagPh = new Tag(_PLACEHOLDER_TAG$3, { 29129 name: ph.closeName 29130 }, [closeEx, closeTagAsText]); 29131 return [startTagPh, ...this.serialize(ph.children), closeTagPh]; 29132 } 29133 29134 visitPlaceholder(ph, context) { 29135 const interpolationAsText = new Text$1(`{{${ph.value}}}`); // Example tag needs to be not-empty for TC. 29136 29137 const exTag = new Tag(_EXAMPLE_TAG, {}, [interpolationAsText]); 29138 return [// TC requires PH to have a non empty EX, and uses the text node to show the "original" value. 29139 new Tag(_PLACEHOLDER_TAG$3, { 29140 name: ph.name 29141 }, [exTag, interpolationAsText])]; 29142 } 29143 29144 visitIcuPlaceholder(ph, context) { 29145 const icuExpression = ph.value.expression; 29146 const icuType = ph.value.type; 29147 const icuCases = Object.keys(ph.value.cases).map(value => value + ' {...}').join(' '); 29148 const icuAsText = new Text$1(`{${icuExpression}, ${icuType}, ${icuCases}}`); 29149 const exTag = new Tag(_EXAMPLE_TAG, {}, [icuAsText]); 29150 return [// TC requires PH to have a non empty EX, and uses the text node to show the "original" value. 29151 new Tag(_PLACEHOLDER_TAG$3, { 29152 name: ph.name 29153 }, [exTag, icuAsText])]; 29154 } 29155 29156 serialize(nodes) { 29157 return [].concat(...nodes.map(node => node.visit(this))); 29158 } 29159 29160} 29161 29162function digest(message) { 29163 return decimalDigest(message); 29164} // TC requires at least one non-empty example on placeholders 29165 29166 29167class ExampleVisitor { 29168 addDefaultExamples(node) { 29169 node.visit(this); 29170 return node; 29171 } 29172 29173 visitTag(tag) { 29174 if (tag.name === _PLACEHOLDER_TAG$3) { 29175 if (!tag.children || tag.children.length == 0) { 29176 const exText = new Text$1(tag.attrs['name'] || '...'); 29177 tag.children = [new Tag(_EXAMPLE_TAG, {}, [exText])]; 29178 } 29179 } else if (tag.children) { 29180 tag.children.forEach(node => node.visit(this)); 29181 } 29182 } 29183 29184 visitText(text) {} 29185 29186 visitDeclaration(decl) {} 29187 29188 visitDoctype(doctype) {} 29189 29190} // XMB/XTB placeholders can only contain A-Z, 0-9 and _ 29191 29192 29193function toPublicName(internalName) { 29194 return internalName.toUpperCase().replace(/[^A-Z0-9_]/g, '_'); 29195} 29196/** 29197 * @license 29198 * Copyright Google LLC All Rights Reserved. 29199 * 29200 * Use of this source code is governed by an MIT-style license that can be 29201 * found in the LICENSE file at https://angular.io/license 29202 */ 29203 29204/* Closure variables holding messages must be named `MSG_[A-Z0-9]+` */ 29205 29206 29207const CLOSURE_TRANSLATION_VAR_PREFIX = 'MSG_'; 29208/** 29209 * Prefix for non-`goog.getMsg` i18n-related vars. 29210 * Note: the prefix uses lowercase characters intentionally due to a Closure behavior that 29211 * considers variables like `I18N_0` as constants and throws an error when their value changes. 29212 */ 29213 29214const TRANSLATION_VAR_PREFIX = 'i18n_'; 29215/** Name of the i18n attributes **/ 29216 29217const I18N_ATTR = 'i18n'; 29218const I18N_ATTR_PREFIX = 'i18n-'; 29219/** Prefix of var expressions used in ICUs */ 29220 29221const I18N_ICU_VAR_PREFIX = 'VAR_'; 29222/** Prefix of ICU expressions for post processing */ 29223 29224const I18N_ICU_MAPPING_PREFIX = 'I18N_EXP_'; 29225/** Placeholder wrapper for i18n expressions **/ 29226 29227const I18N_PLACEHOLDER_SYMBOL = '�'; 29228 29229function isI18nAttribute(name) { 29230 return name === I18N_ATTR || name.startsWith(I18N_ATTR_PREFIX); 29231} 29232 29233function isI18nRootNode(meta) { 29234 return meta instanceof Message; 29235} 29236 29237function isSingleI18nIcu(meta) { 29238 return isI18nRootNode(meta) && meta.nodes.length === 1 && meta.nodes[0] instanceof Icu; 29239} 29240 29241function hasI18nMeta(node) { 29242 return !!node.i18n; 29243} 29244 29245function hasI18nAttrs(element) { 29246 return element.attrs.some(attr => isI18nAttribute(attr.name)); 29247} 29248 29249function icuFromI18nMessage(message) { 29250 return message.nodes[0]; 29251} 29252 29253function wrapI18nPlaceholder(content, contextId = 0) { 29254 const blockId = contextId > 0 ? `:${contextId}` : ''; 29255 return `${I18N_PLACEHOLDER_SYMBOL}${content}${blockId}${I18N_PLACEHOLDER_SYMBOL}`; 29256} 29257 29258function assembleI18nBoundString(strings, bindingStartIndex = 0, contextId = 0) { 29259 if (!strings.length) return ''; 29260 let acc = ''; 29261 const lastIdx = strings.length - 1; 29262 29263 for (let i = 0; i < lastIdx; i++) { 29264 acc += `${strings[i]}${wrapI18nPlaceholder(bindingStartIndex + i, contextId)}`; 29265 } 29266 29267 acc += strings[lastIdx]; 29268 return acc; 29269} 29270 29271function getSeqNumberGenerator(startsAt = 0) { 29272 let current = startsAt; 29273 return () => current++; 29274} 29275 29276function placeholdersToParams(placeholders) { 29277 const params = {};
29278 placeholders.forEach((values, key) => { 29279 params[key] = literal(values.length > 1 ? `[${values.join('|')}]` : values[0]); 29280 }); 29281 return params; 29282} 29283 29284function updatePlaceholderMap(map, name, ...values) { 29285 const current = map.get(name) || []; 29286 current.push(...values); 29287 map.set(name, current); 29288} 29289 29290function assembleBoundTextPlaceholders(meta, bindingStartIndex = 0, contextId = 0) { 29291 const startIdx = bindingStartIndex; 29292 const placeholders = new Map(); 29293 const node = meta instanceof Message ? meta.nodes.find(node => node instanceof Container) : meta; 29294 29295 if (node) { 29296 node.children.filter(child => child instanceof Placeholder).forEach((child, idx) => { 29297 const content = wrapI18nPlaceholder(startIdx + idx, contextId); 29298 updatePlaceholderMap(placeholders, child.name, content); 29299 }); 29300 } 29301 29302 return placeholders; 29303} 29304/** 29305 * Format the placeholder names in a map of placeholders to expressions. 29306 * 29307 * The placeholder names are converted from "internal" format (e.g. `START_TAG_DIV_1`) to "external" 29308 * format (e.g. `startTagDiv_1`). 29309 * 29310 * @param params A map of placeholder names to expressions. 29311 * @param useCamelCase whether to camelCase the placeholder name when formatting. 29312 * @returns A new map of formatted placeholder names to expressions. 29313 */ 29314 29315 29316function formatI18nPlaceholderNamesInMap(params = {}, useCamelCase) { 29317 const _params = {}; 29318 29319 if (params && Object.keys(params).length) { 29320 Object.keys(params).forEach(key => _params[formatI18nPlaceholderName(key, useCamelCase)] = params[key]); 29321 } 29322 29323 return _params; 29324} 29325/** 29326 * Converts internal placeholder names to public-facing format 29327 * (for example to use in goog.getMsg call). 29328 * Example: `START_TAG_DIV_1` is converted to `startTagDiv_1`. 29329 * 29330 * @param name The placeholder name that should be formatted 29331 * @returns Formatted placeholder name 29332 */ 29333 29334 29335function formatI18nPlaceholderName(name, useCamelCase = true) { 29336 const publicName = toPublicName(name); 29337 29338 if (!useCamelCase) { 29339 return publicName; 29340 } 29341 29342 const chunks = publicName.split('_'); 29343 29344 if (chunks.length === 1) { 29345 // if no "_" found - just lowercase the value 29346 return name.toLowerCase(); 29347 } 29348 29349 let postfix; // eject last element if it's a number 29350 29351 if (/^\d+$/.test(chunks[chunks.length - 1])) { 29352 postfix = chunks.pop(); 29353 } 29354 29355 let raw = chunks.shift().toLowerCase(); 29356 29357 if (chunks.length) { 29358 raw += chunks.map(c => c.charAt(0).toUpperCase() + c.slice(1).toLowerCase()).join(''); 29359 } 29360 29361 return postfix ? `${raw}_${postfix}` : raw; 29362} 29363/** 29364 * Generates a prefix for translation const name. 29365 * 29366 * @param extra Additional local prefix that should be injected into translation var name 29367 * @returns Complete translation const prefix 29368 */ 29369 29370 29371function getTranslationConstPrefix(extra) { 29372 return `${CLOSURE_TRANSLATION_VAR_PREFIX}${extra}`.toUpperCase(); 29373} 29374/** 29375 * Generate AST to declare a variable. E.g. `var I18N_1;`. 29376 * @param variable the name of the variable to declare. 29377 */ 29378 29379 29380function declareI18nVariable(variable) { 29381 return new DeclareVarStmt(variable.name, undefined, INFERRED_TYPE, undefined, variable.sourceSpan); 29382} 29383/** 29384 * @license 29385 * Copyright Google LLC All Rights Reserved. 29386 * 29387 * Use of this source code is governed by an MIT-style license that can be 29388 * found in the LICENSE file at https://angular.io/license 29389 */ 29390 29391/** 29392 * Checks whether an object key contains potentially unsafe chars, thus the key should be wrapped in 29393 * quotes. Note: we do not wrap all keys into quotes, as it may have impact on minification and may 29394 * bot work in some cases when object keys are mangled by minifier. 29395 * 29396 * TODO(FW-1136): this is a temporary solution, we need to come up with a better way of working with 29397 * inputs that contain potentially unsafe chars. 29398 */ 29399 29400 29401const UNSAFE_OBJECT_KEY_NAME_REGEXP = /[-.]/; 29402/** Name of the temporary to use during data binding */ 29403 29404const TEMPORARY_NAME = '_t'; 29405/** Name of the context parameter passed into a template function */ 29406 29407const CONTEXT_NAME = 'ctx'; 29408/** Name of the RenderFlag passed into a template function */ 29409 29410const RENDER_FLAGS = 'rf'; 29411/** The prefix reference variables */ 29412 29413const REFERENCE_PREFIX = '_r'; 29414/** The name of the implicit context reference */ 29415 29416const IMPLICIT_REFERENCE = '$implicit'; 29417/** Non bindable attribute name **/ 29418 29419const NON_BINDABLE_ATTR = 'ngNonBindable'; 29420/** Name for the variable keeping track of the context returned by `ɵɵrestoreView`. */ 29421 29422const RESTORED_VIEW_CONTEXT_NAME = 'restoredCtx'; 29423/** 29424 * Maximum length of a single instruction chain. Because our output AST uses recursion, we're 29425 * limited in how many expressions we can nest before we reach the call stack limit. This 29426 * length is set very conservatively in order to reduce the chance of problems. 29427 */ 29428 29429const MAX_CHAIN_LENGTH = 500; 29430/** Instructions that support chaining. */ 29431 29432const 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]); 29433/** Generates a call to a single instruction. */ 29434
29435function invokeInstruction(span, reference, params) { 29436 return importExpr(reference, null, span).callFn(params, span); 29437} 29438/** 29439 * Creates an allocator for a temporary variable. 29440 * 29441 * A variable declaration is added to the statements the first time the allocator is invoked. 29442 */ 29443 29444 29445function temporaryAllocator(statements, name) { 29446 let temp = null; 29447 return () => { 29448 if (!temp) { 29449 statements.push(new DeclareVarStmt(TEMPORARY_NAME, undefined, DYNAMIC_TYPE)); 29450 temp = variable(name); 29451 } 29452 29453 return temp; 29454 }; 29455} 29456 29457function invalid(arg) { 29458 throw new Error(`Invalid state: Visitor ${this.constructor.name} doesn't handle ${arg.constructor.name}`); 29459} 29460 29461function asLiteral(value) { 29462 if (Array.isArray(value)) { 29463 return literalArr(value.map(asLiteral)); 29464 } 29465 29466 return literal(value, INFERRED_TYPE); 29467} 29468 29469function conditionallyCreateMapObjectLiteral(keys, keepDeclared) { 29470 if (Object.getOwnPropertyNames(keys).length > 0) { 29471 return mapToExpression(keys, keepDeclared); 29472 } 29473 29474 return null; 29475} 29476 29477function mapToExpression(map, keepDeclared) { 29478 return literalMap(Object.getOwnPropertyNames(map).map(key => { 29479 // canonical syntax: `dirProp: publicProp` 29480 const value = map[key]; 29481 let declaredName; 29482 let publicName; 29483 let minifiedName; 29484 let needsDeclaredName; 29485 29486 if (Array.isArray(value)) { 29487 [publicName, declaredName] = value; 29488 minifiedName = key; 29489 needsDeclaredName = publicName !== declaredName; 29490 } else { 29491 minifiedName = declaredName = key; 29492 publicName = value; 29493 needsDeclaredName = false; 29494 } 29495 29496 return { 29497 key: minifiedName, 29498 // put quotes around keys that contain potentially unsafe characters 29499 quoted: UNSAFE_OBJECT_KEY_NAME_REGEXP.test(minifiedName), 29500 value: keepDeclared && needsDeclaredName ? literalArr([asLiteral(publicName), asLiteral(declaredName)]) : asLiteral(publicName) 29501 }; 29502 })); 29503} 29504/** 29505 * Remove trailing null nodes as they are implied. 29506 */ 29507 29508 29509function trimTrailingNulls(parameters) { 29510 while (isNull(parameters[parameters.length - 1])) { 29511 parameters.pop(); 29512 } 29513 29514 return parameters; 29515} 29516 29517function getQueryPredicate(query, constantPool) { 29518 if (Array.isArray(query.predicate)) { 29519 let predicate = []; 29520 query.predicate.forEach(selector => { 29521 // Each item in predicates array may contain strings with comma-separated refs 29522 // (for ex. 'ref, ref1, ..., refN'), thus we extract individual refs and store them 29523 // as separate array entities 29524 const selectors = selector.split(',').map(token => literal(token.trim())); 29525 predicate.push(...selectors); 29526 }); 29527 return constantPool.getConstLiteral(literalArr(predicate), true); 29528 } else { 29529 // The original predicate may have been wrapped in a `forwardRef()` call. 29530 switch (query.predicate.forwardRef) { 29531 case 0 29532 /* ForwardRefHandling.None */ 29533 : 29534 case 2 29535 /* ForwardRefHandling.Unwrapped */ 29536 : 29537 return query.predicate.expression; 29538 29539 case 1 29540 /* ForwardRefHandling.Wrapped */ 29541 : 29542 return importExpr(Identifiers.resolveForwardRef).callFn([query.predicate.expression]); 29543 } 29544 } 29545} 29546/** 29547 * A representation for an object literal used during codegen of definition objects. The generic 29548 * type `T` allows to reference a documented type of the generated structure, such that the 29549 * property names that are set can be resolved to their documented declaration. 29550 */ 29551 29552 29553class DefinitionMap { 29554 constructor() { 29555 this.values = []; 29556 } 29557 29558 set(key, value) { 29559 if (value) { 29560 this.values.push({ 29561 key: key, 29562 value, 29563 quoted: false 29564 }); 29565 } 29566 } 29567 29568 toLiteralMap() { 29569 return literalMap(this.values); 29570 } 29571 29572} 29573/** 29574 * Extract a map of properties to values for a given element or template node, which can be used 29575 * by the directive matching machinery. 29576 * 29577 * @param elOrTpl the element or template in question 29578 * @return an object set up for directive matching. For attributes on the element/template, this 29579 * object maps a property name to its (static) value. For any bindings, this map simply maps the 29580 * property name to an empty string. 29581 */ 29582 29583 29584function getAttrsForDirectiveMatching(elOrTpl) { 29585 const attributesMap = {}; 29586 29587 if (elOrTpl instanceof Template && elOrTpl.tagName !== 'ng-template') {
29588 elOrTpl.templateAttrs.forEach(a => attributesMap[a.name] = ''); 29589 } else { 29590 elOrTpl.attributes.forEach(a => { 29591 if (!isI18nAttribute(a.name)) { 29592 attributesMap[a.name] = a.value; 29593 } 29594 }); 29595 elOrTpl.inputs.forEach(i => { 29596 attributesMap[i.name] = ''; 29597 }); 29598 elOrTpl.outputs.forEach(o => { 29599 attributesMap[o.name] = ''; 29600 }); 29601 } 29602 29603 return attributesMap; 29604} 29605/** 29606 * Gets the number of arguments expected to be passed to a generated instruction in the case of 29607 * interpolation instructions. 29608 * @param interpolation An interpolation ast 29609 */ 29610 29611 29612function getInterpolationArgsLength(interpolation) { 29613 const { 29614 expressions, 29615 strings 29616 } = interpolation; 29617 29618 if (expressions.length === 1 && strings.length === 2 && strings[0] === '' && strings[1] === '') { 29619 // If the interpolation has one interpolated value, but the prefix and suffix are both empty 29620 // strings, we only pass one argument, to a special instruction like `propertyInterpolate` or 29621 // `textInterpolate`. 29622 return 1; 29623 } else { 29624 return expressions.length + strings.length; 29625 } 29626} 29627/** 29628 * Generates the final instruction call statements based on the passed in configuration. 29629 * Will try to chain instructions as much as possible, if chaining is supported. 29630 */ 29631 29632 29633function getInstructionStatements(instructions) { 29634 const statements = []; 29635 let pendingExpression = null; 29636 let pendingExpressionType = null; 29637 let chainLength = 0; 29638 29639 for (const current of instructions) { 29640 const resolvedParams = (typeof current.paramsOrFn === 'function' ? current.paramsOrFn() : current.paramsOrFn) ?? []; 29641 const params = Array.isArray(resolvedParams) ? resolvedParams : [resolvedParams]; // If the current instruction is the same as the previous one 29642 // and it can be chained, add another call to the chain. 29643 29644 if (chainLength < MAX_CHAIN_LENGTH && pendingExpressionType === current.reference && CHAINABLE_INSTRUCTIONS.has(pendingExpressionType)) { 29645 // We'll always have a pending expression when there's a pending expression type. 29646 pendingExpression = pendingExpression.callFn(params, pendingExpression.sourceSpan); 29647 chainLength++; 29648 } else { 29649 if (pendingExpression !== null) { 29650 statements.push(pendingExpression.toStmt()); 29651 } 29652 29653 pendingExpression = invokeInstruction(current.span, current.reference, params); 29654 pendingExpressionType = current.reference; 29655 chainLength = 0; 29656 } 29657 } // Since the current instruction adds the previous one to the statements, 29658 // we may be left with the final one at the end that is still pending. 29659 29660 29661 if (pendingExpression !== null) { 29662 statements.push(pendingExpression.toStmt()); 29663 } 29664 29665 return statements; 29666} 29667/** 29668 * @license 29669 * Copyright Google LLC All Rights Reserved. 29670 * 29671 * Use of this source code is governed by an MIT-style license that can be 29672 * found in the LICENSE file at https://angular.io/license 29673 */ 29674 29675 29676function compileInjectable(meta, resolveForwardRefs) { 29677 let result = null; 29678 const factoryMeta = { 29679 name: meta.name, 29680 type: meta.type, 29681 internalType: meta.internalType, 29682 typeArgumentCount: meta.typeArgumentCount, 29683 deps: [], 29684 target: FactoryTarget$1.Injectable 29685 }; 29686 29687 if (meta.useClass !== undefined) { 29688 // meta.useClass has two modes of operation. Either deps are specified, in which case `new` is 29689 // used to instantiate the class with dependencies injected, or deps are not specified and 29690 // the factory of the class is used to instantiate it. 29691 // 29692 // A special case exists for useClass: Type where Type is the injectable type itself and no 29693 // deps are specified, in which case 'useClass' is effectively ignored. 29694 const useClassOnSelf = meta.useClass.expression.isEquivalent(meta.internalType); 29695 let deps = undefined; 29696 29697 if (meta.deps !== undefined) { 29698 deps = meta.deps; 29699 } 29700 29701 if (deps !== undefined) { 29702 // factory: () => new meta.useClass(...deps) 29703 result = compileFactoryFunction({ ...factoryMeta, 29704 delegate: meta.useClass.expression, 29705 delegateDeps: deps, 29706 delegateType: R3FactoryDelegateType.Class 29707 }); 29708 } else if (useClassOnSelf) { 29709 result = compileFactoryFunction(factoryMeta); 29710 } else { 29711 result = { 29712 statements: [], 29713 expression: delegateToFactory(meta.type.value, meta.useClass.expression, resolveForwardRefs) 29714 }; 29715 } 29716 } else if (meta.useFactory !== undefined) { 29717 if (meta.deps !== undefined) { 29718 result = compileFactoryFunction({ ...factoryMeta, 29719 delegate: meta.useFactory, 29720 delegateDeps: meta.deps || [], 29721 delegateType: R3FactoryDelegateType.Function 29722 }); 29723 } else { 29724 result = { 29725 statements: [],
29726 expression: fn([], [new ReturnStatement(meta.useFactory.callFn([]))]) 29727 }; 29728 } 29729 } else if (meta.useValue !== undefined) { 29730 // Note: it's safe to use `meta.useValue` instead of the `USE_VALUE in meta` check used for 29731 // client code because meta.useValue is an Expression which will be defined even if the actual 29732 // value is undefined. 29733 result = compileFactoryFunction({ ...factoryMeta, 29734 expression: meta.useValue.expression 29735 }); 29736 } else if (meta.useExisting !== undefined) { 29737 // useExisting is an `inject` call on the existing token. 29738 result = compileFactoryFunction({ ...factoryMeta, 29739 expression: importExpr(Identifiers.inject).callFn([meta.useExisting.expression]) 29740 }); 29741 } else { 29742 result = { 29743 statements: [], 29744 expression: delegateToFactory(meta.type.value, meta.internalType, resolveForwardRefs) 29745 }; 29746 } 29747 29748 const token = meta.internalType; 29749 const injectableProps = new DefinitionMap(); 29750 injectableProps.set('token', token); 29751 injectableProps.set('factory', result.expression); // Only generate providedIn property if it has a non-null value 29752 29753 if (meta.providedIn.expression.value !== null) { 29754 injectableProps.set('providedIn', convertFromMaybeForwardRefExpression(meta.providedIn)); 29755 } 29756 29757 const expression = importExpr(Identifiers.ɵɵdefineInjectable).callFn([injectableProps.toLiteralMap()], undefined, true); 29758 return { 29759 expression, 29760 type: createInjectableType(meta), 29761 statements: result.statements 29762 }; 29763} 29764 29765function createInjectableType(meta) { 29766 return new ExpressionType(importExpr(Identifiers.InjectableDeclaration, [typeWithParameters(meta.type.type, meta.typeArgumentCount)])); 29767} 29768 29769function delegateToFactory(type, internalType, unwrapForwardRefs) { 29770 if (type.node === internalType.node) { 29771 // The types are the same, so we can simply delegate directly to the type's factory. 29772 // ``` 29773 // factory: type.ɵfac 29774 // ``` 29775 return internalType.prop('ɵfac'); 29776 } 29777 29778 if (!unwrapForwardRefs) { 29779 // The type is not wrapped in a `forwardRef()`, so we create a simple factory function that 29780 // accepts a sub-type as an argument. 29781 // ``` 29782 // factory: function(t) { return internalType.ɵfac(t); } 29783 // ``` 29784 return createFactoryFunction(internalType); 29785 } // The internalType is actually wrapped in a `forwardRef()` so we need to resolve that before 29786 // calling its factory. 29787 // ``` 29788 // factory: function(t) { return core.resolveForwardRef(type).ɵfac(t); } 29789 // ``` 29790 29791 29792 const unwrappedType = importExpr(Identifiers.resolveForwardRef).callFn([internalType]); 29793 return createFactoryFunction(unwrappedType); 29794} 29795 29796function createFactoryFunction(type) { 29797 return fn([new FnParam('t', DYNAMIC_TYPE)], [new ReturnStatement
29797(type.prop('ɵfac').callFn([variable('t')]))]); 29798} 29799/** 29800 * @license 29801 * Copyright Google LLC All Rights Reserved. 29802 * 29803 * Use of this source code is governed by an MIT-style license that can be 29804 * found in the LICENSE file at https://angular.io/license 29805 */ 29806 29807 29808const UNUSABLE_INTERPOLATION_REGEXPS = [/^\s*$/, /[<>]/, /^[{}]$/, /&(#|[a-z])/i, /^\/\// // comment 29809]; 29810 29811function assertInterpolationSymbols(identifier, value) { 29812 if (value != null && !(Array.isArray(value) && value.length == 2)) { 29813 throw new Error(`Expected '${identifier}' to be an array, [start, end].`); 29814 } else if (value != null) { 29815 const start = value[0]; 29816 const end = value[1]; // Check for unusable interpolation symbols 29817 29818 UNUSABLE_INTERPOLATION_REGEXPS.forEach(regexp => { 29819 if (regexp.test(start) || regexp.test(end)) { 29820 throw new Error(`['${start}', '${end}'] contains unusable interpolation symbol.`); 29821 } 29822 }); 29823 } 29824} 29825/** 29826 * @license 29827 * Copyright Google LLC All Rights Reserved. 29828 * 29829 * Use of this source code is governed by an MIT-style license that can be 29830 * found in the LICENSE file at https://angular.io/license 29831 */ 29832 29833 29834class InterpolationConfig { 29835 constructor(start, end) { 29836 this.start = start; 29837 this.end = end; 29838 } 29839 29840 static fromArray(markers) { 29841 if (!markers) { 29842 return DEFAULT_INTERPOLATION_CONFIG; 29843 } 29844 29845 assertInterpolationSymbols('interpolation', markers); 29846 return new InterpolationConfig(markers[0], markers[1]); 29847 } 29848 29849} 29850 29851const DEFAULT_INTERPOLATION_CONFIG = new InterpolationConfig('{{', '}}'); 29852/** 29853 * @license 29854 * Copyright Google LLC All Rights Reserved. 29855 * 29856 * Use of this source code is governed by an MIT-style license that can be 29857 * found in the LICENSE file at https://angular.io/license 29858 */ 29859 29860const $EOF = 0; 29861const $BSPACE = 8; 29862const $TAB = 9; 29863const $LF = 10; 29864const $VTAB = 11; 29865const $FF = 12; 29866const $CR = 13; 29867const $SPACE = 32; 29868const $BANG = 33; 29869const $DQ = 34; 29870const $HASH = 35; 29871const $$ = 36; 29872const $PERCENT = 37; 29873const $AMPERSAND = 38; 29874const $SQ = 39; 29875const $LPAREN = 40; 29876const $RPAREN = 41; 29877const $STAR = 42; 29878const $PLUS = 43; 29879const $COMMA = 44; 29880const $MINUS = 45; 29881const $PERIOD = 46; 29882const $SLASH = 47; 29883const $COLON = 58; 29884const $SEMICOLON = 59; 29885const $LT = 60; 29886const $EQ = 61; 29887const $GT = 62; 29888const $QUESTION = 63; 29889const $0 = 48; 29890const $7 = 55; 29891const $9 = 57; 29892const $A = 65; 29893const $E = 69; 29894const $F = 70; 29895const $X = 88; 29896const $Z = 90; 29897const $LBRACKET = 91; 29898const $BACKSLASH = 92; 29899const $RBRACKET = 93; 29900const $CARET = 94; 29901const $_ = 95; 29902const $a = 97; 29903const $b = 98; 29904const $e = 101; 29905const $f = 102; 29906const $n = 110; 29907const $r = 114; 29908const $t = 116; 29909const $u = 117; 29910const $v = 118; 29911const $x = 120; 29912const $z = 122; 29913const $LBRACE = 123; 29914const $BAR = 124; 29915const $RBRACE = 125; 29916const $NBSP = 160; 29917const $PIPE = 124; 29918const $TILDA = 126; 29919const $AT = 64; 29920const $BT = 96; 29921 29922function isWhitespace(code) { 29923 return code >= $TAB && code <= $SPACE || code == $NBSP; 29924} 29925 29926function isDigit(code) { 29927 return $0 <= code && code <= $9; 29928} 29929 29930function isAsciiLetter(code) { 29931 return code >= $a && code <= $z || code >= $A && code <= $Z; 29932} 29933 29934function isAsciiHexDigit(code) { 29935 return code >= $a && code <= $f || code >= $A && code <= $F || isDigit(code); 29936} 29937 29938function isNewLine(code) { 29939 return code === $LF || code === $CR; 29940} 29941 29942function isOctalDigit(code) { 29943 return $0 <= code && code <= $7; 29944} 29945 29946function isQuote(code) { 29947 return code === $SQ || code === $DQ || code === $BT; 29948} 29949/** 29950 * @license 29951 * Copyright Google LLC All Rights Reserved. 29952 * 29953 * Use of this source code is governed by an MIT-style license that can be 29954 * found in the LICENSE file at https://angular.io/license 29955 */ 29956 29957 29958class ParseLocation { 29959 constructor(file, offset, line, col) { 29960 this.file = file; 29961 this.offset = offset; 29962 this.line = line; 29963 this.col = col; 29964 } 29965 29966 toString() { 29967 return this.offset != null ? `${this.file.url}@${this.line}:${this.col}` : this.file.url; 29968 } 29969 29970 moveBy(delta) { 29971 const source = this.file.content; 29972 const len = source.length; 29973 let offset = this.offset; 29974 let line = this.line; 29975 let col = this.col; 29976 29977 while (offset > 0 && delta < 0) { 29978 offset--; 29979 delta++; 29980 const ch = source.charCodeAt(offset); 29981 29982 if (ch == $LF) { 29983 line--; 29984 const priorLine = source.substring(0, offset - 1).lastIndexOf(String.fromCharCode($LF)); 29985 col = priorLine > 0 ? offset - priorLine : offset; 29986 } else { 29987 col--; 29988 } 29989 } 29990 29991 while (offset < len && delta > 0) { 29992 const ch = source.charCodeAt(offset); 29993 offset++; 29994 delta--; 29995 29996 if (ch == $LF) { 29997 line++; 29998 col = 0; 29999 } else { 30000 col++; 30001 } 30002 } 30003 30004 return new ParseLocation(this.file, offset, line, col); 30005 } // Return the source around the location 30006 // Up to `maxChars` or `maxLines` on each side of the location 30007 30008 30009 getContext(maxChars, maxLines) { 30010 const content = this.file.content; 30011 let startOffset = this.offset; 30012 30013 if (startOffset != null) { 30014 if (startOffset > content.length - 1) { 30015 startOffset = content.length - 1; 30016 } 30017 30018 let endOffset = startOffset; 30019 let ctxChars = 0; 30020 let ctxLines = 0; 30021 30022 while (ctxChars < maxChars && startOffset > 0) { 30023 startOffset--; 30024 ctxChars++; 30025 30026 if (content[startOffset] == '\n') { 30027 if (++ctxLines == maxLines) { 30028 break; 30029 } 30030 } 30031 } 30032 30033 ctxChars = 0; 30034 ctxLines = 0; 30035 30036 while (ctxChars < maxChars && endOffset < content.length - 1) { 30037 endOffset++; 30038 ctxChars++; 30039 30040 if (content[endOffset] == '\n') { 30041 if (++ctxLines == maxLines) { 30042 break; 30043 } 30044 } 30045 } 30046 30047 return { 30048 before: content.substring(startOffset, this.offset), 30049 after: content.substring(this.offset, endOffset + 1) 30050 }; 30051 } 30052 30053 return null; 30054 } 30055 30056} 30057 30058class ParseSourceFile {
30059 constructor(content, url) { 30060 this.content = content; 30061 this.url = url; 30062 } 30063 30064} 30065 30066class ParseSourceSpan { 30067 /** 30068 * Create an object that holds information about spans of tokens/nodes captured during 30069 * lexing/parsing of text. 30070 * 30071 * @param start 30072 * The location of the start of the span (having skipped leading trivia). 30073 * Skipping leading trivia makes source-spans more "user friendly", since things like HTML 30074 * elements will appear to begin at the start of the opening tag, rather than at the start of any 30075 * leading trivia, which could include newlines. 30076 * 30077 * @param end 30078 * The location of the end of the span. 30079 * 30080 * @param fullStart 30081 * The start of the token without skipping the leading trivia. 30082 * This is used by tooling that splits tokens further, such as extracting Angular interpolations 30083 * from text tokens. Such tooling creates new source-spans relative to the original token's 30084 * source-span. If leading trivia characters have been skipped then the new source-spans may be 30085 * incorrectly offset. 30086 * 30087 * @param details 30088 * Additional information (such as identifier names) that should be associated with the span. 30089 */ 30090 constructor(start, end, fullStart = start, details = null) { 30091 this.start = start; 30092 this.end = end; 30093 this.fullStart = fullStart; 30094 this.details = details; 30095 } 30096 30097 toString() { 30098 return this.start.file.content.substring(this.start.offset, this.end.offset); 30099 } 30100 30101} 30102 30103var ParseErrorLevel; 30104 30105(function (ParseErrorLevel) { 30106 ParseErrorLevel[ParseErrorLevel["WARNING"] = 0] = "WARNING"; 30107 ParseErrorLevel[ParseErrorLevel["ERROR"] = 1] = "ERROR"; 30108})(ParseErrorLevel || (ParseErrorLevel = {})); 30109 30110class ParseError { 30111 constructor(span, msg, level = ParseErrorLevel.ERROR) { 30112 this.span = span; 30113 this.msg = msg; 30114 this.level = level; 30115 } 30116 30117 contextualMessage() { 30118 const ctx = this.span.start.getContext(100, 3); 30119 return ctx ? `${this.msg} ("${ctx.before}[${ParseErrorLevel[this.level]} ->]${ctx.after}")` : this.msg; 30120 } 30121 30122 toString() { 30123 const details = this.span.details ? `, ${this.span.details}` : ''; 30124 return `${this.contextualMessage()}: ${this.span.start}${details}`; 30125 } 30126 30127} 30128/** 30129 * Generates Source Span object for a given R3 Type for JIT mode. 30130 * 30131 * @param kind Component or Directive. 30132 * @param typeName name of the Component or Directive. 30133 * @param sourceUrl reference to Component or Directive source. 30134 * @returns instance of ParseSourceSpan that represent a given Component or Directive. 30135 */ 30136 30137 30138function r3JitTypeSourceSpan(kind, typeName, sourceUrl) { 30139 const sourceFileName = `in ${kind} ${typeName} in ${sourceUrl}`; 30140 const sourceFile = new ParseSourceFile('', sourceFileName); 30141 return new ParseSourceSpan(new ParseLocation(sourceFile, -1, -1, -1), new ParseLocation(sourceFile, -1, -1, -1)); 30142} 30143 30144let _anonymousTypeIndex = 0; 30145 30146function identifierName(compileIdentifier) { 30147 if (!compileIdentifier || !compileIdentifier.reference) { 30148 return null; 30149 } 30150 30151 const ref = compileIdentifier.reference; 30152 30153 if (ref['__anonymousType']) { 30154 return ref['__anonymousType']; 30155 } 30156 30157 if (ref['__forward_ref__']) { 30158 // We do not want to try to stringify a `forwardRef()` function because that would cause the 30159 // inner function to be evaluated too early, defeating the whole point of the `forwardRef`. 30160 return '__forward_ref__';
30161 } 30162 30163 let identifier = stringify(ref); 30164 30165 if (identifier.indexOf('(') >= 0) { 30166 // case: anonymous functions! 30167 identifier = `anonymous_${_anonymousTypeIndex++}`; 30168 ref['__anonymousType'] = identifier; 30169 } else { 30170 identifier = sanitizeIdentifier(identifier); 30171 } 30172 30173 return identifier; 30174} 30175 30176function sanitizeIdentifier(name) { 30177 return name.replace(/\W/g, '_'); 30178} 30179/** 30180 * @license 30181 * Copyright Google LLC All Rights Reserved. 30182 * 30183 * Use of this source code is governed by an MIT-style license that can be 30184 * found in the LICENSE file at https://angular.io/license 30185 */ 30186 30187/** 30188 * In TypeScript, tagged template functions expect a "template object", which is an array of 30189 * "cooked" strings plus a `raw` property that contains an array of "raw" strings. This is 30190 * typically constructed with a function called `__makeTemplateObject(cooked, raw)`, but it may not 30191 * be available in all environments. 30192 * 30193 * This is a JavaScript polyfill that uses __makeTemplateObject when it's available, but otherwise 30194 * creates an inline helper with the same functionality. 30195 * 30196 * In the inline function, if `Object.defineProperty` is available we use that to attach the `raw` 30197 * array. 30198 */ 30199 30200
30201const makeTemplateObjectPolyfill = '(this&&this.__makeTemplateObject||function(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e})'; 30202 30203class AbstractJsEmitterVisitor extends AbstractEmitterVisitor { 30204 constructor() { 30205 super(false); 30206 } 30207 30208 visitWrappedNodeExpr(ast, ctx) { 30209 throw new Error('Cannot emit a WrappedNodeExpr in Javascript.'); 30210 } 30211 30212 visitDeclareVarStmt(stmt, ctx) { 30213 ctx.print(stmt, `var ${stmt.name}`); 30214 30215 if (stmt.value) { 30216 ctx.print(stmt, ' = '); 30217 stmt.value.visitExpression(this, ctx); 30218 } 30219 30220 ctx.println(stmt, `;`); 30221 return null; 30222 } 30223 30224 visitTaggedTemplateExpr(ast, ctx) { 30225 // The following convoluted piece of code is effectively the downlevelled equivalent of 30226 // ``` 30227 // tag`...` 30228 // ``` 30229 // which is effectively like: 30230 // ``` 30231 // tag(__makeTemplateObject(cooked, raw), expression1, expression2, ...); 30232 // ``` 30233 const elements = ast.template.elements; 30234 ast.tag.visitExpression(this, ctx); 30235 ctx.print(ast, `(${makeTemplateOb
30235jectPolyfill}(`); 30236 ctx.print(ast, `[${elements.map(part => escapeIdentifier(part.text, false)).join(', ')}], `); 30237 ctx.print(ast, `[${elements.map(part => escapeIdentifier(part.rawText, false)).join(', ')}])`); 30238 ast.template.expressions.forEach(expression => { 30239 ctx.print(ast, ', '); 30240 expression.visitExpression(this, ctx); 30241 }); 30242 ctx.print(ast, ')'); 30243 return null; 30244 } 30245 30246 visitFunctionExpr(ast, ctx) { 30247 ctx.print(ast, `function${ast.name ? ' ' + ast.name : ''}(`); 30248 30249 this._visitParams(ast.params, ctx); 30250 30251 ctx.println(ast, `) {`); 30252 ctx.incIndent(); 30253 this.visitAllStatements(ast.statements, ctx); 30254 ctx.decIndent(); 30255 ctx.print(ast, `}`); 30256 return null; 30257 } 30258 30259 visitDeclareFunctionStmt(stmt, ctx) { 30260 ctx.print(stmt, `function ${stmt.name}(`); 30261 30262 this._visitParams(stmt.params, ctx); 30263 30264 ctx.println(stmt, `) {`); 30265 ctx.incIndent(); 30266 this.visitAllStatements(stmt.statements, ctx); 30267 ctx.decIndent(); 30268 ctx.println(stmt, `}`); 30269 return null; 30270 } 30271 30272 visitLocalizedString(ast, ctx) { 30273 // The following convoluted piece of code is effectively the downlevelled equivalent of 30274 // ``` 30275 // $localize `...` 30276 // ``` 30277 // which is effectively like: 30278 // ```
30279 // $localize(__makeTemplateObject(cooked, raw), expression1, expression2, ...); 30280 // ``` 30281 ctx.print(ast, `$localize(${makeTemplateObjectPolyfill}(`); 30282 const parts = [ast.serializeI18nHead()]; 30283 30284 for (let i = 1; i < ast.messageParts.length; i++) { 30285 parts.push(ast.serializeI18nTemplatePart(i)); 30286 } 30287 30288 ctx.print(ast, `[${parts.map(part => escapeIdentifier(part.cooked, false)).join(', ')}], `); 30289 ctx.print(ast, `[${parts.map(part => escapeIdentifier(part.raw, false)).join(', ')}])`); 30290 ast.expressions.forEach(expression => { 30291 ctx.print(ast, ', '); 30292 expression.visitExpression(this, ctx); 30293 }); 30294 ctx.print(ast, ')'); 30295 return null; 30296 } 30297 30298 _visitParams(params, ctx) { 30299 this.visitAllObjects(param => ctx.print(null, param.name), params, ctx, ','); 30300 } 30301 30302} 30303/** 30304 * @license 30305 * Copyright Google LLC All Rights Reserved. 30306 * 30307 * Use of this source code is governed by an MIT-style license that can be 30308 * found in the LICENSE file at https://angular.io/license 30309 */ 30310 30311/** 30312 * The Trusted Types policy, or null if Trusted Types are not 30313 * enabled/supported, or undefined if the policy has not been created yet. 30314 */ 30315 30316 30317let policy; 30318/** 30319 * Returns the Trusted Types policy, or null if Trusted Types are not 30320 * enabled/supported. The first call to this function will create the policy. 30321 */ 30322 30323function getPolicy() { 30324 if (policy === undefined) { 30325 policy = null; 30326 30327 if (_global.trustedTypes) { 30328 try { 30329 policy = _global.trustedTypes.createPolicy('angular#unsafe-jit', { 30330 createScript: s => s 30331 }); 30332 } catch {// trustedTypes.createPolicy throws if called with a name that is 30333 // already registered, even in report-only mode. Until the API changes, 30334 // catch the error not to break the applications functionally. In such 30335 // cases, the code will fall back to using strings. 30336 } 30337 } 30338 } 30339 30340 return policy; 30341} 30342/** 30343 * Unsafely promote a string to a TrustedScript, falling back to strings when 30344 * Trusted Types are not available. 30345 * @security In particular, it must be assured that the provided string will 30346 * never cause an XSS vulnerability if used in a context that will be 30347 * interpreted and executed as a script by a browser, e.g. when calling eval. 30348 */ 30349 30350 30351function trustedScriptFromString(script) { 30352 return getPolicy()?.createScript(script) || script; 30353} 30354/** 30355 * Unsafely call the Function constructor with the given string arguments. 30356 * @security This is a security-sensitive function; any use of this function 30357 * must go through security review. In particular, it must be assured that it 30358 * is only called from the JIT compiler, as use in other code can lead to XSS 30359 * vulnerabilities. 30360 */ 30361 30362 30363function newTrustedFunctionForJIT(...args) { 30364 if (!_global.trustedTypes) { 30365 // In environments that don't support Trusted Types, fall back to the most 30366 // straightforward implementation: 30367 return new Function(...args); 30368 } // Chrome currently does not support passing TrustedScript to the Function 30369 // constructor. The following implements the workaround proposed on the page 30370 // below, where the Chromium bug is also referenced: 30371 // https://github.com/w3c/webappsec-trusted-types/wiki/Trusted-Types-for-function-constructor 30372 30373 30374 const fnArgs = args.slice(0, -1).join(','); 30375 const fnBody = args[args.length - 1]; 30376 const body = `(function anonymous(${fnArgs} 30377) { ${fnBody} 30378})`; // Using eval directly confuses the compiler and prevents this module from 30379 // being stripped out of JS binaries even if not used. The global['eval'] 30380 // indirection fixes that. 30381 30382 const fn = _global['eval'](trustedScriptFromString(body)); 30383 30384 if (fn.bind === undefined) { 30385 // Workaround for a browser bug that only exists in Chrome 83, where passing 30386 // a TrustedScript to eval just returns the TrustedScript back without 30387 // evaluating it. In that case, fall back to the most straightforward 30388 // implementation: 30389 return new Function(...args); 30390 } // To completely mimic the behavior of calling "new Function", two more 30391 // things need to happen: 30392 // 1. Stringifying the resulting function should return its source code 30393 30394 30395 fn.toString = () => body; // 2. When calling the resulting function, `this` should refer to `global` 30396 30397 30398 return fn.bind(_global); // When Trusted Types support in Function constructors is widely available, 30399 // the implementation of this function can be simplified to: 30400 // return new Function(...args.map(a => trustedScriptFromString(a))); 30401} 30402/** 30403 * @license 30404 * Copyright Google LLC All Rights Reserved. 30405 * 30406 * Use of this source code is governed by an MIT-style license that can be 30407 * found in the LICENSE file at https://angular.io/license 30408 */ 30409 30410/** 30411 * A helper class to manage the evaluation of JIT generated code. 30412 */ 30413 30414 30415class JitEvaluator { 30416 /** 30417 * 30418 * @param sourceUrl The URL of the generated code. 30419 * @param statements An array of Angular statement AST nodes to be evaluated. 30420 * @param refResolver Resolves `o.ExternalReference`s into values. 30421 * @param createSourceMaps If true then create a source-map for the generated code and include it 30422 * inline as a source-map comment. 30423 * @returns A map of all the variables in the generated code. 30424 */ 30425 evaluateStatements(sourceUrl, statements, refResolver, createSourceMaps) { 30426 const converter = new JitEmitterVisitor(refResolver); 30427 const ctx = EmitterVisitorContext.createRoot(); // Ensure generated code is in strict mode 30428 30429 if (statements.length >
30429 0 && !isUseStrictStatement(statements[0])) { 30430 statements = [literal('use strict').toStmt(), ...statements]; 30431 } 30432 30433 converter.visitAllStatements(statements, ctx); 30434 converter.createReturnStmt(ctx); 30435 return this.evaluateCode(sourceUrl, ctx, converter.getArgs(), createSourceMaps); 30436 } 30437 /** 30438 * Evaluate a piece of JIT generated code. 30439 * @param sourceUrl The URL of this generated code. 30440 * @param ctx A context object that contains an AST of the code to be evaluated. 30441 * @param vars A map containing the names and values of variables that the evaluated code might 30442 * reference. 30443 * @param createSourceMap If true then create a source-map for the generated code and include it 30444 * inline as a source-map comment. 30445 * @returns The result of evaluating the code. 30446 */ 30447 30448 30449 evaluateCode(sourceUrl, ctx, vars, createSourceMap) { 30450 let fnBody = `"use strict";${ctx.toSource()}\n//# sourceURL=${sourceUrl}`; 30451 const fnArgNames = []; 30452 const fnArgValues = []; 30453 30454 for (const argName in vars) { 30455 fnArgValues.push(vars[argName]); 30456 fnArgNames.push(argName); 30457 } 30458 30459 if (createSourceMap) { 30460 // using `new Function(...)` generates a header, 1 line of no arguments, 2 lines otherwise 30461 // E.g. ``` 30462 // function anonymous(a,b,c 30463 // /**/) { ... }``` 30464 // We don't want to hard code this fact, so we auto detect it via an empty function first. 30465 const emptyFn = newTrustedFunctionForJIT(...fnArgNames.concat('return null;')).toString(); 30466 const headerLines = emptyFn.slice(0, emptyFn.indexOf('return null;')).split('\n').length - 1; 30467 fnBody += `\n${ctx.toSourceMapGenerator(sourceUrl, headerLines).toJsComment()}`; 30468 } 30469 30470 const fn = newTrustedFunctionForJIT(...fnArgNames.concat(fnBody)); 30471 return this.executeFunction(fn, fnArgValues); 30472 } 30473 /** 30474 * Execute a JIT generated function by calling it. 30475 * 30476 * This method can be overridden in tests to capture the functions that are generated 30477 * by this `JitEvaluator` class. 30478 * 30479 * @param fn A function to execute. 30480 * @param args The arguments to pass to the function being executed. 30481 * @returns The return value of the executed function. 30482 */ 30483 30484 30485 executeFunction(fn, args) { 30486 return fn(...args); 30487 } 30488 30489} 30490/** 30491 * An Angular AST visitor that converts AST nodes into executable JavaScript code. 30492 */ 30493 30494 30495class JitEmitterVisitor extends AbstractJsEmitterVisitor { 30496 constructor(refResolver) { 30497 super(); 30498 this.refResolver = refResolver; 30499 this._evalArgNames = []; 30500 this._evalArgValues = []; 30501 this._evalExportedVars = []; 30502 } 30503 30504 createReturnStmt(ctx) {
30505 const stmt = new ReturnStatement(new LiteralMapExpr(this._evalExportedVars.map(resultVar => new LiteralMapEntry(resultVar, variable(resultVar), false)))); 30506 stmt.visitStatement(this, ctx); 30507 } 30508 30509 getArgs() { 30510 const result = {}; 30511 30512 for (let i = 0; i < this._evalArgNames.length; i++) { 30513 result[this._evalArgNames[i]] = this._evalArgValues[i]; 30514 } 30515 30516 return result; 30517 } 30518 30519 visitExternalExpr(ast, ctx) { 30520 this._emitReferenceToExternal(ast, this.refResolver.resolveExternalReference(ast.value), ctx); 30521 30522 return null; 30523 } 30524 30525 visitWrappedNodeExpr(ast, ctx) { 30526 this._emitReferenceToExternal(ast, ast.node, ctx); 30527 30528 return null; 30529 } 30530 30531 visitDeclareVarStmt(stmt, ctx) { 30532 if (stmt.hasModifier(StmtModifier.Exported)) { 30533 this._evalExportedVars.push(stmt.name); 30534 } 30535 30536 return super.visitDeclareVarStmt(stmt, ctx); 30537 } 30538 30539 visitDeclareFunctionStmt(stmt, ctx) { 30540 if (stmt.hasModifier(StmtModifier.Exported)) { 30541 this._evalExportedVars.push(stmt.name); 30542 } 30543 30544 return super.visitDeclareFunctionStmt(stmt, ctx); 30545 } 30546 30547 _emitReferenceToExternal(ast, value, ctx) { 30548 let id = this._evalArgValues.indexOf(value); 30549 30550 if (id === -1) { 30551 id = this._evalArgValues.length; 30552 30553 this._evalArgValues.push(value); 30554 30555 const name = identifierName({ 30556 reference: value 30557 }) || 'val'; 30558 30559 this._evalArgNames.push(`jit_${name}_${id}`); 30560 } 30561 30562 ctx.print(ast, this._evalArgNames[id]); 30563 } 30564 30565} 30566 30567function isUseStrictStatement(statement) { 30568 return statement.isEquivalent(literal('use strict').toStmt()); 30569} 30570/** 30571 * @license 30572 * Copyright Google LLC All Rights Reserved. 30573 * 30574 * Use of this source code is governed by an MIT-style license that can be 30575 * found in the LICENSE file at https://angular.io/license 30576 */ 30577 30578 30579function compileInjector(meta) { 30580 const definitionMap = new DefinitionMap(); 30581 30582 if (meta.providers !== null) { 30583 definitionMap.set('providers', meta.providers); 30584 } 30585 30586 if (meta.imports.length > 0) { 30587 definitionMap.set('imports', literalArr(meta.imports)); 30588 } 30589 30590 const expression = importExpr(Identifiers.defineInjector).callFn([definitionMap.toLiteralMap()], undefined, true); 30591 const type = createInjectorType(meta); 30592 return { 30593 expression, 30594 type, 30595 statements: [] 30596 }; 30597} 30598 30599function createInjectorType(meta) { 30600 return new ExpressionType(importExpr(Identifiers.InjectorDeclaration, [new ExpressionType(meta.type.type)])); 30601} 30602/** 30603 * @license 30604 * Copyright Google LLC All Rights Reserved. 30605 * 30606 * Use of this source code is governed by an MIT-style license that can be 30607 * found in the LICENSE file at https://angular.io/license 30608 */ 30609 30610/** 30611 * Implementation of `CompileReflector` which resolves references to @angular/core 30612 * symbols at runtime, according to a consumer-provided mapping. 30613 * 30614 * Only supports `resolveExternalReference`, all other methods throw. 30615 */ 30616 30617 30618class R3JitReflector { 30619 constructor(context) { 30620 this.context = context; 30621 } 30622 30623 resolveExternalReference(ref) { 30624 // This reflector only handles @angular/core imports. 30625 if (ref.moduleName !== '@angular/core') { 30626 throw new Error(`Cannot resolve external reference to ${ref.moduleName}, only references to @angular/core are supported.`); 30627 } 30628
30629 if (!this.context.hasOwnProperty(ref.name)) { 30630 throw new Error(`No value provided for @angular/core symbol '${ref.name}'.`); 30631 } 30632 30633 return this.context[ref.name]; 30634 } 30635 30636} 30637/** 30638 * @license 30639 * Copyright Google LLC All Rights Reserved. 30640 * 30641 * Use of this source code is governed by an MIT-style license that can be 30642 * found in the LICENSE file at https://angular.io/license 30643 */ 30644 30645/** 30646 * How the selector scope of an NgModule (its declarations, imports, and exports) should be emitted 30647 * as a part of the NgModule definition. 30648 */ 30649 30650 30651var R3SelectorScopeMode; 30652 30653(function (R3SelectorScopeMode) { 30654 /** 30655 * Emit the declarations inline into the module definition. 30656 * 30657 * This option is useful in certain contexts where it's known that JIT support is required. The 30658 * tradeoff here is that this emit style prevents directives and pipes from being tree-shaken if 30659 * they are unused, but the NgModule is used. 30660 */ 30661 R3SelectorScopeMode[R3SelectorScopeMode["Inline"] = 0] = "Inline"; 30662 /** 30663 * Emit the declarations using a side effectful function call, `ɵɵsetNgModuleScope`, that is 30664 * guarded with the `ngJitMode` flag. 30665 * 30666 * This form of emit supports JIT and can be optimized away if the `ngJitMode` flag is set to 30667 * false, which allows unused directives and pipes to be tree-shaken. 30668 */ 30669 30670 R3SelectorScopeMode[R3SelectorScopeMode["SideEffect"] = 1] = "SideEffect"; 30671 /** 30672 * Don't generate selector scopes at all. 30673 * 30674 * This is useful for contexts where JIT support is known to be unnecessary. 30675 */ 30676 30677 R3SelectorScopeMode[R3SelectorScopeMode["Omit"] = 2] = "Omit"; 30678})(R3SelectorScopeMode || (R3SelectorScopeMode = {})); 30679/** 30680 * Construct an `R3NgModuleDef` for the given `R3NgModuleMetadata`. 30681 */ 30682 30683 30684function compileNgModule(meta) { 30685 const { 30686 adjacentType, 30687 internalType, 30688 bootstrap, 30689 declarations, 30690 imports, 30691 exports, 30692 schemas, 30693 containsForwardDecls, 30694 selectorScopeMode, 30695 id 30696 } = meta; 30697 const statements = []; 30698 const definitionMap = new DefinitionMap(); 30699 definitionMap.set('type', internalType); 30700 30701 if (bootstrap.length > 0) { 30702 definitionMap.set('bootstrap', refsToArray(bootstrap, containsForwardDecls)); 30703 } 30704 30705 if (selectorScopeMode === R3SelectorScopeMode.Inline) { 30706 // If requested to emit scope information inline, pass the `declarations`, `imports` and 30707 // `exports` to the `ɵɵdefineNgModule()` call directly. 30708 if (declarations.length > 0) { 30709 definitionMap.set('declarations', refsToArray(declarations, containsForwardDecls)); 30710 } 30711 30712 if (imports.length > 0) { 30713 definitionMap.set('imports', refsToArray(imports, containsForwardDecls)); 30714 } 30715 30716 if (exports.length > 0) { 30717 definitionMap.set('exports', refsToArray(exports, containsForwardDecls)); 30718 } 30719 } else if (selectorScopeMode === R3SelectorScopeMode.SideEffect) { 30720 // In this mode, scope information is not passed into `ɵɵdefineNgModule` as it 30721 // would prevent tree-shaking of the declarations, imports and exports references. Instead, it's 30722 // patched onto the NgModule definition with a `ɵɵsetNgModuleScope` call that's guarded by the 30723 // `ngJitMode` flag. 30724 const setNgModuleScopeCall = generateSetNgModuleScopeCall(meta); 30725 30726 if (setNgModuleScopeCall !== null) { 30727 statements.push(setNgModuleScopeCall); 30728 } 30729 } else {// Selector scope emit was not requested, so skip it. 30730 } 30731 30732 if (schemas !== null && schemas.length > 0) { 30733 definitionMap.set('schemas', literalArr(schemas.map(ref => ref.value))); 30734 } 30735 30736 if (id !== null) { 30737 definitionMap.set('id', id); // Generate a side-effectful call to register this NgModule by its id, as per the semantics of 30738 // NgModule ids. 30739 30740 statements.push(importExpr(Identifiers.registerNgModuleType).callFn([adjacentType, id]).toStmt()); 30741 } 30742 30743 const expression = importExpr(Identifiers.defineNgModule).callFn([definitionMap.toLiteralMap()], undefined, true); 30744 const type = createNgModuleType(meta); 30745 return { 30746 expression, 30747 type, 30748 statements 30749 }; 30750} 30751/** 30752 * This function is used in JIT mode to generate the call to `ɵɵdefineNgModule()` from a call to
30753 * `ɵɵngDeclareNgModule()`. 30754 */ 30755 30756 30757function compileNgModuleDeclarationExpression(meta) { 30758 const definitionMap = new DefinitionMap(); 30759 definitionMap.set('type', new WrappedNodeExpr(meta.type)); 30760 30761 if (meta.bootstrap !== undefined) { 30762 definitionMap.set('bootstrap', new WrappedNodeExpr(meta.bootstrap)); 30763 } 30764 30765 if (meta.declarations !== undefined) { 30766 definitionMap.set('declarations', new WrappedNodeExpr(meta.declarations)); 30767 } 30768 30769 if (meta.imports !== undefined) { 30770 definitionMap.set('imports', new WrappedNodeExpr(meta.imports)); 30771 } 30772 30773 if (meta.exports !== undefined) { 30774 definitionMap.set('exports', new WrappedNodeExpr(meta.exports)); 30775 } 30776 30777 if (meta.schemas !== undefined) { 30778 definitionMap.set('schemas', new WrappedNodeExpr(meta.schemas)); 30779 } 30780 30781 if (meta.id !== undefined) { 30782 definitionMap.set('id', new WrappedNodeExpr(meta.id)); 30783 } 30784 30785 return importExpr(Identifiers.defineNgModule).callFn([definitionMap.toLiteralMap()]); 30786} 30787 30788function createNgModuleType({ 30789 type: moduleType, 30790 declarations, 30791 exports, 30792 imports, 30793 includeImportTypes, 30794 publicDeclarationTypes 30795}) { 30796 return new ExpressionType(importExpr(Identifiers.NgModuleDeclaration, [new ExpressionType(moduleType.type), publicDeclarationTypes === null ? tupleTypeOf(declarations) : tupleOfTypes(publicDeclarationTypes), includeImportTypes ? tupleTypeOf(imports) : NONE_TYPE, tupleTypeOf(exports)])); 30797} 30798/** 30799 * Generates a function call to `ɵɵsetNgModuleScope` with all necessary information so that the 30800 * transitive module scope can be computed during runtime in JIT mode. This call is marked pure 30801 * such that the references to declarations, imports and exports may be elided causing these 30802 * symbols to become tree-shakeable. 30803 */ 30804 30805 30806function generateSetNgModuleScopeCall(meta) { 30807 const { 30808 adjacentType: moduleType, 30809 declarations, 30810 imports, 30811 exports, 30812 containsForwardDecls 30813 } = meta; 30814 const scopeMap = new DefinitionMap(); 30815 30816 if (declarations.length > 0) { 30817 scopeMap.set('declarations', refsToArray(declarations, containsForwardDecls)); 30818 } 30819 30820 if (imports.length > 0) { 30821 scopeMap.set('imports', refsToArray(imports, containsForwardDecls)); 30822 } 30823 30824 if (exports.length > 0) { 30825 scopeMap.set('exports', refsToArray(exports, containsForwardDecls)); 30826 } 30827 30828 if (Object.keys(scopeMap.values).length === 0) { 30829 return null; 30830 } // setNgModuleScope(...) 30831 30832 30833 const fnCall = new InvokeFunctionExpr( 30834 /* fn */ 30835 importExpr(Identifiers.setNgModuleScope), 30836 /* args */ 30837 [moduleType, scopeMap.toLiteralMap()]); // (ngJitMode guard) && setNgModuleScope(...) 30838 30839 const guardedCall = jitOnlyGuardedExpression(fnCall); // function() { (ngJitMode guard) && setNgModuleScope(...); } 30840 30841 const iife = new FunctionExpr( 30842 /* params */ 30843 [], 30844 /* statements */ 30845 [guardedCall.toStmt()]); // (function() { (ngJitMode guard) && setNgModuleScope(...); })() 30846 30847 const iifeCall = new InvokeFunctionExpr( 30848 /* fn */ 30849 iife, 30850 /* args */ 30851 []); 30852 return iifeCall.toStmt(); 30853} 30854 30855function tupleTypeOf(exp) { 30856 const types = exp.map(ref => typeofExpr(ref.type)); 30857 return exp.length > 0 ? expressionType(literalArr(types)) : NONE_TYPE; 30858} 30859 30860function tupleOfTypes(types) { 30861 const typeofTypes = types.map(type => typeofExpr(type)); 30862 return types.length > 0 ? expressionType(literalArr(typeofTypes)) : NONE_TYPE; 30863} 30864/** 30865 * @license 30866 * Copyright Google LLC All Rights Reserved. 30867 * 30868 * Use of this source code is governed by an MIT-style license that can be 30869 * found in the LICENSE file at https://angular.io/license 30870 */ 30871 30872 30873function compilePipeFromMetadata(metadata) { 30874 const definitionMapValues = []; // e.g. `name: 'myPipe'` 30875 30876 definitionMapValues.push({ 30877 key: 'name', 30878 value: literal(metadata.pipeName), 30879 quoted: false 30880 }); // e.g. `type: MyPipe` 30881 30882 definitionMapValues.push({ 30883 key: 'type', 30884 value: metadata.type.value, 30885 quoted: false 30886 }); // e.g. `pure: true` 30887 30888 definitionMapValues.push({ 30889 key: 'pure', 30890 value: literal(metadata.pure), 30891 quoted: false 30892 }); 30893 30894 if (metadata.isStandalone) { 30895 definitionMapValues.push({ 30896 key: 'standalone', 30897 value: literal(true), 30898 quoted: false 30899 }); 30900 } 30901 30902 const expression = importExpr(Identifiers.definePipe).callFn([literalMap(definitionMapValues)], undefined, true); 30903 const type = createPipeType(metadata); 30904 return { 30905 expression, 30906 type, 30907 statements: [] 30908 }; 30909} 30910 30911function createPipeType(metadata) { 30912 return new ExpressionType(importExpr(Identifiers.PipeDeclaration, [typeWithParameters(metadata.type.type, metadata.typeArgumentCount), new ExpressionType(new LiteralExpr(metadata.pipeName)), new ExpressionType(new LiteralExpr(metadata.isStandalone))])); 30913} 30914/** 30915 * @license 30916 * Copyright Google LLC All Rights Reserved. 30917 * 30918 * Use of this source code is governed by an MIT-style license that can be 30919 * found in the LICENSE file at https://angular.io/license 30920 */ 30921 30922 30923var R3TemplateDependencyKind; 30924 30925(function (R3TemplateDependencyKind) { 30926 R3TemplateDependencyKind[R3TemplateDependencyKind["Directive"] = 0] = "Directive"; 30927 R3TemplateDependencyKind[R3TemplateDependencyKind["Pipe"] = 1] = "Pipe"; 30928 R3TemplateDependencyKind[R3TemplateDependencyKind["NgModule"] = 2] = "NgModule"; 30929})(R3TemplateDependencyKind || (R3TemplateDependencyKind = {})); 30930/** 30931 * @license 30932 * Copyright Google LLC All Rights Reserved. 30933 * 30934 * Use of this source code is governed by an MIT-style license that can be 30935 * found in the LICENSE file at https://angular.io/license 30936 */ 30937 30938 30939class ParserError { 30940 constructor(message, input, errLocation, ctxLocation) { 30941 this.input = input; 30942 this.errLocation = errLocation; 30943 this.ctxLocation = ctxLocation; 30944 this.message = `Parser Error: ${message} ${errLocation} [${input}] in ${ctxLocation}`; 30945 } 30946 30947} 30948 30949class ParseSpan { 30950 constructor(start, end) { 30951 this.start = start; 30952 this.end = end; 30953 } 30954 30955 toAbsolute(absoluteOffset) { 30956 return new AbsoluteSourceSpan(absoluteOffset + this.start, absoluteOffset + this.end); 30957 } 30958 30959} 30960 30961class AST { 30962 constructor(span, 30963 /** 30964 * Absolute location of the expression AST in a source code file. 30965 */ 30966 sourceSpan) { 30967 this.span = span; 30968 this.sourceSpan = sourceSpan; 30969 } 30970 30971 toString() { 30972 return 'AST'; 30973 } 30974 30975} 30976 30977class ASTWithName extends AST { 30978 constructor(span, sourceSpan, nameSpan) { 30979 super(span, sourceSpan); 30980 this.nameSpan = nameSpan; 30981 } 30982 30983} 30984 30985class EmptyExpr extends AST { 30986 visit(visitor, context = null) {// do nothing 30987 } 30988 30989} 30990 30991class ImplicitReceiver extends AST { 30992 visit(visitor, context = null) { 30993 return visitor.visitImplicitReceiver(this, context); 30994 } 30995 30996} 30997/** 30998 * Receiver when something is accessed through `this` (e.g. `this.foo`). Note that this class 30999 * inherits from `ImplicitReceiver`, because accessing something through `this` is treated the 31000 * same as accessing it implicitly inside of an Angular template (e.g. `[attr.title]="this.title"` 31001 * is the same as `[attr.title]="title"`.). Inheriting allows for the `this` accesses to be treated 31002 * the same as implicit ones, except for a couple of exceptions like `$event` and `$any`. 31003 * TODO: we should find a way for this class not to extend from `ImplicitReceiver` in the future. 31004 */ 31005 31006 31007class ThisReceiver extends ImplicitReceiver { 31008 visit(visitor, context = null) { 31009 return visitor.visitThisReceiver?.(this, context); 31010 } 31011 31012} 31013/** 31014 * Multiple expressions separated by a semicolon. 31015 */ 31016 31017 31018class Chain extends AST { 31019 constructor(span, sourceSpan, expressions) { 31020 super(span, sourceSpan); 31021 this.expressions = expressions; 31022 } 31023 31024 visit(visitor, context = null) { 31025 return visitor.visitChain(this, context); 31026 } 31027 31028} 31029 31030class Conditional extends AST { 31031 constructor(span, sourceSpan, condition, trueExp, falseExp) { 31032 super(span, sourceSpan); 31033 this.condition = condition; 31034 this.trueExp = trueExp; 31035 this.falseExp = falseExp; 31036 } 31037 31038 visit(visitor, context = null) { 31039 return visitor.visitConditional(this, context); 31040 } 31041 31042} 31043 31044class PropertyRead extends ASTWithName { 31045 constructor(span, sourceSpan, nameSpan, receiver, name) { 31046 super(span, sourceSpan, nameSpan); 31047 this.receiver = receiver; 31048 this.name = name; 31049 } 31050 31051 visit(visitor, context = null) { 31052 return visitor.visitPropertyRead(this, context); 31053 } 31054 31055} 31056 31057class PropertyWrite extends ASTWithName { 31058 constructor(span, sourceSpan, nameSpan, receiver, name, value) { 31059 super(span, sourceSpan, nameSpan); 31060 this.receiver = receiver; 31061 this.name = name; 31062 this.value = value; 31063 } 31064 31065 visit(visitor, context = null) { 31066 return visitor.visitPropertyWrite(this, context); 31067 } 31068 31069} 31070 31071class SafePropertyRead extends ASTWithName { 31072 constructor(span, sourceSpan, nameSpan, receiver, name) { 31073 super(span, sourceSpan, nameSpan); 31074 this.receiver = receiver; 31075 this.name = name; 31076 } 31077 31078 visit(visitor, context = null) { 31079 return visitor.visitSafePropertyRead(this, context); 31080 } 31081 31082} 31083 31084class KeyedRead extends AST { 31085 constructor(span, sourceSpan, receiver, key) { 31086 super(span, sourceSpan); 31087 this.receiver = receiver; 31088 this.key = key; 31089 } 31090 31091 visit(visitor, context = null) { 31092 return visitor.visitKeyedRead(this, context); 31093 } 31094 31095} 31096 31097class SafeKeyedRead extends AST { 31098 constructor(span, sourceSpan, receiver, key) { 31099 super(span, sourceSpan); 31100 this.receiver = receiver; 31101 this.key = key; 31102 } 31103 31104 visit(visitor, context = null) { 31105 return visitor.visitSafeKeyedRead(this, context); 31106 } 31107 31108} 31109 31110class KeyedWrite extends AST { 31111 constructor(span, sourceSpan, receiver, key, value) { 31112 super(span, sourceSpan); 31113 this.receiver = receiver; 31114 this.key = key; 31115 this.value = value; 31116 } 31117 31118 visit(visitor, context = null) { 31119 return visitor.visitKeyedWrite(this, context); 31120 } 31121 31122} 31123 31124class BindingPipe extends ASTWithName { 31125 constructor(span, sourceSpan, exp, name, args, nameSpan) { 31126 super(span, sourceSpan, nameSpan); 31127 this.exp = exp; 31128 this.name = name; 31129 this.args = args; 31130 } 31131 31132 visit(visitor, context = null) { 31133 return visitor.visitPipe(this, context); 31134 } 31135 31136} 31137 31138class LiteralPrimitive extends AST { 31139 constructor(span, sourceSpan, value) { 31140 super(span, sourceSpan); 31141 this.value = value; 31142 } 31143 31144 visit(visitor, context = null) { 31145 return visitor.visitLiteralPrimitive(this, context); 31146 } 31147 31148} 31149 31150class LiteralArray extends AST { 31151 constructor(span, sourceSpan, expressions) { 31152 super(span, sourceSpan); 31153 this.expressions = expressions; 31154 } 31155 31156 visit(visitor, context = null) { 31157 return visitor.visitLiteralArray(this, context); 31158 } 31159 31160} 31161 31162class LiteralMap extends AST { 31163 constructor(span, sourceSpan, keys, values) { 31164 super(span, sourceSpan); 31165 this.keys = keys; 31166 this.values = values; 31167 } 31168 31169 visit(visitor, context = null) { 31170 return visitor.visitLiteralMap(this, context); 31171 } 31172 31173} 31174 31175class Interpolation extends AST { 31176 constructor(span, sourceSpan, strings, expressions) { 31177 super(span, sourceSpan); 31178 this.strings = strings; 31179 this.expressions = expressions; 31180 } 31181 31182 visit(visitor, context = null) { 31183 return visitor.visitInterpolation(this, context); 31184 } 31185 31186} 31187 31188class Binary extends AST { 31189 constructor(span, sourceSpan, operation, left, right) { 31190 super(span, sourceSpan); 31191 this.operation = operation; 31192 this.left = left; 31193 this.right = right; 31194 } 31195 31196 visit(visitor, context = null) { 31197 return visitor.visitBinary(this, context); 31198 } 31199 31200} 31201/** 31202 * For backwards compatibility reasons, `Unary` inherits from `Binary` and mimics the binary AST 31203 * node that was originally used. This inheritance relation can be deleted in some future major, 31204 * after consumers have been given a chance to fully support Unary. 31205 */ 31206 31207 31208class Unary extends Binary { 31209 /** 31210 * During the deprecation period this constructor is private, to avoid consumers from creating 31211 * a `Unary` with the fallback properties for `Binary`. 31212 */ 31213 constructor(span, sourceSpan, operator, expr, binaryOp, binaryLeft, binaryRight) { 31214 super(span, sourceSpan, binaryOp, binaryLeft, binaryRight); 31215 this.operator = operator; 31216 this.expr = expr; // Redeclare the properties that are inherited from `Binary` as `never`, as consumers should not 31217 // depend on these fields when operating on `Unary`. 31218 31219 this.left = null; 31220 this.right = null; 31221 this.operation = null; 31222 } 31223 /** 31224 * Creates a unary minus expression "-x", represented as `Binary` using "0 - x". 31225 */ 31226 31227 31228 static createMinus(span, sourceSpan, expr) { 31229 return new Unary(span, sourceSpan, '-', expr, '-', new LiteralPrimitive(span, sourceSpan, 0), expr); 31230 } 31231 /** 31232 * Creates a unary plus expression "+x", represented as `Binary` using "x - 0". 31233 */ 31234 31235 31236 static createPlus(span, sourceSpan, expr) { 31237 return new Unary(span, sourceSpan, '+', expr, '-', expr, new LiteralPrimitive(span, sourceSpan, 0)); 31238 } 31239 31240 visit(visitor, context = null) { 31241 if (visitor.visitUnary !== undefined) { 31242 return visitor.visitUnary(this, context); 31243 } 31244 31245 return visitor.visitBinary(this, context); 31246 } 31247 31248} 31249 31250class PrefixNot extends AST { 31251 constructor(span, sourceSpan, expression) { 31252 super(span, sourceSpan); 31253 this.expression = expression; 31254 } 31255 31256 visit(visitor, context = null) { 31257 return visitor.visitPrefixNot(this, context); 31258 } 31259 31260} 31261 31262class NonNullAssert extends AST { 31263 constructor(span, sourceSpan, expression) { 31264 super(span, sourceSpan); 31265 this.expression = expression; 31266 } 31267 31268 visit(visitor, context = null) { 31269 return visitor.visitNonNullAssert(this, context); 31270 } 31271 31272} 31273 31274class Call extends AST { 31275 constructor(span, sourceSpan, receiver, args, argumentSpan) { 31276 super(span, sourceSpan); 31277 this.receiver = receiver; 31278 this.args = args; 31279 this.argumentSpan = argumentSpan; 31280 } 31281 31282 visit(visitor, context = null) { 31283 return visitor.visitCall(this, context); 31284 } 31285 31286} 31287 31288class SafeCall extends AST { 31289 constructor(span, sourceSpan, receiver, args, argumentSpan) { 31290 super(span, sourceSpan); 31291 this.receiver = receiver; 31292 this.args = args; 31293 this.argumentSpan = argumentSpan; 31294 } 31295 31296 visit(visitor, context = null) { 31297 return visitor.visitSafeCall(this, context); 31298 } 31299 31300} 31301/** 31302 * Records the absolute position of a text span in a source file, where `start` and `end` are the 31303 * starting and ending byte offsets, respectively, of the text span in a source file. 31304 */ 31305 31306 31307class AbsoluteSourceSpan { 31308 constructor(start, end) { 31309 this.start = start; 31310 this.end = end; 31311 } 31312 31313} 31314 31315class ASTWithSource extends AST { 31316 constructor(ast, source, location, absoluteOffset, errors) { 31317 super(new ParseSpan(0, source === null ? 0 : source.length), new AbsoluteSourceSpan(absoluteOffset, source === null ? absoluteOffset : absoluteOffset + source.length)); 31318 this.ast = ast; 31319 this.source = source; 31320 this.location = location; 31321 this.errors = errors; 31322 } 31323 31324 visit(visitor, context = null) { 31325 if (visitor.visitASTWithSource) { 31326 return visitor.visitASTWithSource(this, context); 31327 } 31328 31329 return this.ast.visit(visitor, context); 31330 } 31331 31332 toString() { 31333 return `${this.source} in ${this.location}`; 31334 } 31335 31336} 31337 31338class VariableBinding { 31339 /** 31340 * @param sourceSpan entire span of the binding. 31341 * @param key name of the LHS along with its span. 31342 * @param value optional value for the RHS along with its span. 31343 */ 31344 constructor(sourceSpan, key, value) { 31345 this.sourceSpan = sourceSpan; 31346 this.key = key; 31347 this.value = value; 31348 } 31349 31350} 31351 31352class ExpressionBinding { 31353 /** 31354 * @param sourceSpan entire span of the binding. 31355 * @param key binding name, like ngForOf, ngForTrackBy, ngIf, along with its 31356 * span. Note that the length of the span may not be the same as 31357 * `key.source.length`. For example,
31358 * 1. key.source = ngFor, key.span is for "ngFor" 31359 * 2. key.source = ngForOf, key.span is for "of" 31360 * 3. key.source = ngForTrackBy, key.span is for "trackBy" 31361 * @param value optional expression for the RHS. 31362 */ 31363 constructor(sourceSpan, key, value) { 31364 this.sourceSpan = sourceSpan; 31365 this.key = key; 31366 this.value = value; 31367 } 31368 31369} 31370 31371class RecursiveAstVisitor { 31372 visit(ast, context) { 31373 // The default implementation just visits every node. 31374 // Classes that extend RecursiveAstVisitor should override this function 31375 // to selectively visit the specified node. 31376 ast.visit(this, context); 31377 } 31378 31379 visitUnary(ast, context) { 31380 this.visit(ast.expr, context); 31381 } 31382 31383 visitBinary(ast, context) { 31384 this.visit(ast.left, context); 31385 this.visit(ast.right, context); 31386 } 31387 31388 visitChain(ast, context) { 31389 this.visitAll(ast.expressions, context); 31390 } 31391 31392 visitConditional(ast, context) { 31393 this.visit(ast.condition, context); 31394 this.visit(ast.trueExp, context); 31395 this.visit(ast.falseExp, context); 31396 } 31397 31398 visitPipe(ast, context) { 31399 this.visit(ast.exp, context); 31400 this.visitAll(ast.args, context); 31401 } 31402 31403 visitImplicitReceiver(ast, context) {} 31404 31405 visitThisReceiver(ast, context) {} 31406 31407 visitInterpolation(ast, context) { 31408 this.visitAll(ast.expressions, context); 31409 } 31410 31411 visitKeyedRead(ast, context) { 31412 this.visit(ast.receiver, context); 31413 this.visit(ast.key, context); 31414 } 31415 31416 visitKeyedWrite(ast, context) { 31417 this.visit(ast.receiver, context); 31418 this.visit(ast.key, context); 31419 this.visit(ast.value, context); 31420 } 31421 31422 visitLiteralArray(ast, context) { 31423 this.visitAll(ast.expressions, context); 31424 } 31425 31426 visitLiteralMap(ast, context) { 31427 this.visitAll(ast.values, context); 31428 } 31429 31430 visitLiteralPrimitive(ast, context) {} 31431 31432 visitPrefixNot(ast, context) { 31433 this.visit(ast.expression, context); 31434 } 31435 31436 visitNonNullAssert(ast, context) { 31437 this.visit(ast.expression, context); 31438 } 31439 31440 visitPropertyRead(ast, context) { 31441 this.visit(ast.receiver, context); 31442 } 31443 31444 visitPropertyWrite(ast, context) { 31445 this.visit(ast.receiver, context); 31446 this.visit(ast.value, context); 31447 } 31448 31449 visitSafePropertyRead(ast, context) { 31450 this.visit(ast.receiver, context); 31451 } 31452 31453 visitSafeKeyedRead(ast, context) { 31454 this.visit(ast.receiver, context); 31455 this.visit(ast.key, context); 31456 } 31457 31458 visitCall(ast, context) { 31459 this.visit(ast.receiver, context); 31460 this.visitAll(ast.args, context); 31461 } 31462 31463 visitSafeCall(ast, context) { 31464 this.visit(ast.receiver, context); 31465 this.visitAll(ast.args, context); 31466 } // This is not part of the AstVisitor interface, just a helper method 31467 31468 31469 visitAll(asts, context) { 31470 for (const ast of asts) { 31471 this.visit(ast, context); 31472 } 31473 } 31474 31475} 31476 31477class AstTransformer { 31478 visitImplicitReceiver(ast, context) { 31479 return ast; 31480 } 31481 31482 visitThisReceiver(ast, context) { 31483 return ast; 31484 } 31485 31486 visitInterpolation(ast, context) { 31487 return new Interpolation(ast.span, ast.sourceSpan, ast.strings, this.visitAll(ast.expressions)); 31488 } 31489 31490 visitLiteralPrimitive(ast, context) { 31491 return new LiteralPrimitive(ast.span, ast.sourceSpan, ast.value); 31492 } 31493 31494 visitPropertyRead(ast, context) { 31495 return new PropertyRead(ast.span, ast.sourceSpan, ast.nameSpan, ast.receiver.visit(this), ast.name); 31496 } 31497 31498 visitPropertyWrite(ast, context) { 31499 return new PropertyWrite(ast.span, ast.sourceSpan, ast.nameSpan, ast.receiver.visit(this), ast.name, ast.value.visit(this)); 31500 } 31501 31502 visitSafePropertyRead(ast, context) { 31503 return new SafePropertyRead(ast.span, ast.sourceSpan, ast.nameSpan, ast.receiver.visit(this), ast.name); 31504 } 31505 31506 visitLiteralArray(ast, context) { 31507 return new LiteralArray(ast.span, ast.sourceSpan, this.visitAll(ast.expressions)); 31508 } 31509 31510 visitLiteralMap(ast, context) { 31511 return new LiteralMap(ast.span, ast.sourceSpan, ast.keys, this.visitAll(ast.values)); 31512 } 31513 31514 visitUnary(ast, context) { 31515 switch (ast.operator) { 31516 case '+': 31517 return Unary.createPlus(ast.span, ast.sourceSpan, ast.expr.visit(this)); 31518 31519 case '-': 31520 return Unary.createMinus(ast.span, ast.sourceSpan, ast.expr.visit(this)); 31521 31522 default: 31523 throw new Error(`Unknown unary operator ${ast.operator}`); 31524 } 31525 } 31526 31527 visitBinary(ast, context) { 31528 return new Binary(ast.span, ast.sourceSpan, ast.operation, ast.left.visit(this), ast.right.visit(this)); 31529 } 31530 31531 visitPrefixNot(ast, context) { 31532 return new PrefixNot(ast.span, ast.sourceSpan, ast.expression.visit(this)); 31533 } 31534 31535 visitNonNullAssert(ast, context) { 31536 return new NonNullAssert(ast.span, ast.sourceSpan, ast.expression.visit(this)); 31537 } 31538 31539 visitConditional(ast, context) { 31540 return new Conditional(ast.span, ast.sourceSpan, ast.condition.visit(this), ast.trueExp.visit(this), ast.falseExp.visit(this)); 31541 } 31542 31543 visitPipe(ast, context) { 31544 return new BindingPipe(ast.span, ast.sourceSpan, ast.exp.visit(this), ast.name, this.visitAll(ast.args), ast.nameSpan); 31545 } 31546 31547 visitKeyedRead(ast, context) { 31548 return new KeyedRead(ast.span, ast.sourceSpan, ast.receiver.visit(this), ast.key.visit(this)); 31549 } 31550 31551 visitKeyedWrite(ast, context) { 31552 return new KeyedWrite(ast.span, ast.sourceSpan, ast.receiver.visit(this), ast.key.visit(this), ast.value.visit(this)); 31553 } 31554 31555 visitCall(ast, context) { 31556 return new Call(ast.span, ast.sourceSpan, ast.receiver.visit(this), this.visitAll(ast.args), ast.argumentSpan); 31557 } 31558 31559 visitSafeCall(ast, context) { 31560 return new SafeCall(ast.span, ast.sourceSpan, ast.receiver.visit(this), this.visitAll(ast.args), ast.argumentSpan); 31561 } 31562 31563 visitAll(asts) { 31564 const res = []; 31565 31566 for (let i = 0; i < asts.length; ++i) { 31567 res[i] = asts[i].visit(this); 31568 } 31569 31570 return res; 31571 } 31572 31573 visitChain(ast, context) { 31574 return new Chain(ast.span, ast.sourceSpan, this.visitAll(ast.expressions)); 31575 } 31576 31577 visitSafeKeyedRead(ast, context) { 31578 return new SafeKeyedRead(ast.span, ast.sourceSpan, ast.receiver.visit(this), ast.key.visit(this)); 31579 } 31580 31581} // A transformer that only creates new nodes if the transformer makes a change or 31582// a change is made a child node. 31583 31584 31585class AstMemoryEfficientTransformer { 31586 visitImplicitReceiver(ast, context) { 31587 return ast; 31588 } 31589 31590 visitThisReceiver(ast, context) { 31591 return ast; 31592 } 31593 31594 visitInterpolation(ast, context) { 31595 const expressions = this.visitAll(ast.expressions); 31596 if (expressions !== ast.expressions) return new Interpolation(ast.span, ast.sourceSpan, ast.strings, expressions); 31597 return ast; 31598 } 31599 31600 visitLiteralPrimitive(ast, context) { 31601 return ast; 31602 } 31603 31604 visitPropertyRead(ast, context) { 31605 const receiver = ast.receiver.visit(this); 31606 31607 if (receiver !== ast.receiver) { 31608 return new PropertyRead(ast.span, ast.sourceSpan, ast.nameSpan, receiver, ast.name); 31609 } 31610 31611 return ast; 31612 } 31613 31614 visitPropertyWrite(ast, context) { 31615 const receiver = ast.receiver.visit(this); 31616 const value = ast.value.visit(this); 31617 31618 if (receiver !== ast.receiver || value !== ast.value) { 31619 return new PropertyWrite(ast.span, ast.sourceSpan, ast.nameSpan, receiver, ast.name, value); 31620 } 31621 31622 return ast; 31623 } 31624 31625 visitSafePropertyRead(ast, context) { 31626 const receiver = ast.receiver.visit(this); 31627 31628 if (receiver !== ast.receiver) { 31629 return new SafePropertyRead(ast.span, ast.sourceSpan, ast.nameSpan, receiver, ast.name); 31630 } 31631 31632 return ast; 31633 } 31634 31635 visitLiteralArray(ast, context) { 31636 const expressions = this.visitAll(ast.expressions); 31637 31638 if (expressions !== ast.expressions) { 31639 return new LiteralArray(ast.span, ast.sourceSpan, expressions); 31640 } 31641 31642 return ast; 31643 } 31644 31645 visitLiteralMap(ast, context) { 31646 const values = this.visitAll(ast.values); 31647 31648 if (values !== ast.values) { 31649 return new LiteralMap(ast.span, ast.sourceSpan, ast.keys, values); 31650 } 31651 31652 return ast; 31653 } 31654 31655 visitUnary(ast, context) { 31656 const expr = ast.expr.visit(this); 31657 31658 if (expr !== ast.expr) { 31659 switch (ast.operator) { 31660 case '+': 31661 return Unary.createPlus(ast.span, ast.sourceSpan, expr); 31662 31663 case '-': 31664 return Unary.createMinus(ast.span, ast.sourceSpan, expr); 31665 31666 default: 31667 throw new Error(`Unknown unary operator ${ast.operator}`); 31668 } 31669 } 31670 31671 return ast; 31672 } 31673 31674 visitBinary(ast, context) { 31675 const left = ast.left.visit(this); 31676 const right = ast.right.visit(this); 31677 31678 if (left !== ast.left || right !== ast.right) { 31679 return new Binary(ast.span, ast.sourceSpan, ast.operation, left, right); 31680 } 31681 31682 return ast; 31683 } 31684 31685 visitPrefixNot(ast, context) { 31686 const expression = ast.expression.visit(this); 31687 31688 if (expression !== ast.expression) { 31689 return new PrefixNot(ast.span, ast.sourceSpan, expression); 31690 } 31691 31692 return ast; 31693 } 31694 31695 visitNonNullAssert(ast, context) { 31696 const expression = ast.expression.visit(this); 31697 31698 if (expression !== ast.expression) { 31699 return new NonNullAssert(ast.span, ast.sourceSpan, expression); 31700 } 31701 31702 return ast; 31703 } 31704 31705 visitConditional(ast, context) { 31706 const condition = ast.condition.visit(this);
31707 const trueExp = ast.trueExp.visit(this); 31708 const falseExp = ast.falseExp.visit(this); 31709 31710 if (condition !== ast.condition || trueExp !== ast.trueExp || falseExp !== ast.falseExp) { 31711 return new Conditional(ast.span, ast.sourceSpan, condition, trueExp, falseExp); 31712 } 31713 31714 return ast; 31715 } 31716 31717 visitPipe(ast, context) { 31718 const exp = ast.exp.visit(this); 31719 const args = this.visitAll(ast.args); 31720 31721 if (exp !== ast.exp || args !== ast.args) { 31722 return new BindingPipe(ast.span, ast.sourceSpan, exp, ast.name, args, ast.nameSpan); 31723 } 31724 31725 return ast; 31726 } 31727 31728 visitKeyedRead(ast, context) { 31729 const obj = ast.receiver.visit(this); 31730 const key = ast.key.visit(this); 31731 31732 if (obj !== ast.receiver || key !== ast.key) { 31733 return new KeyedRead(ast.span, ast.sourceSpan, obj, key); 31734 } 31735 31736 return ast; 31737 } 31738 31739 visitKeyedWrite(ast, context) { 31740 const obj = ast.receiver.visit(this); 31741 const key = ast.key.visit(this); 31742 const value = ast.value.visit(this); 31743 31744 if (obj !== ast.receiver || key !== ast.key || value !== ast.value) { 31745 return new KeyedWrite(ast.span, ast.sourceSpan, obj, key, value); 31746 } 31747 31748 return ast; 31749 } 31750 31751 visitAll(asts) { 31752 const res = []; 31753 let modified = false; 31754 31755 for (let i = 0; i < asts.length; ++i) { 31756 const original = asts[i]; 31757 const value = original.visit(this); 31758 res[i] = value; 31759 modified = modified || value !== original; 31760 } 31761 31762 return modified ? res : asts; 31763 } 31764 31765 visitChain(ast, context) { 31766 const expressions = this.visitAll(ast.expressions); 31767 31768 if (expressions !== ast.expressions) { 31769 return new Chain(ast.span, ast.sourceSpan, expressions); 31770 } 31771 31772 return ast; 31773 } 31774 31775 visitCall(ast, context) { 31776 const receiver = ast.receiver.visit(this); 31777 const args = this.visitAll(ast.args); 31778 31779 if (receiver !== ast.receiver || args !== ast.args) { 31780 return new Call(ast.span, ast.sourceSpan, receiver, args, ast.argumentSpan); 31781 } 31782 31783 return ast; 31784 } 31785 31786 visitSafeCall(ast, context) { 31787 const receiver = ast.receiver.visit(this); 31788 const args = this.visitAll(ast.args); 31789 31790 if (receiver !== ast.receiver || args !== ast.args) { 31791 return new SafeCall(ast.span, ast.sourceSpan, receiver, args, ast.argumentSpan); 31792 } 31793 31794 return ast; 31795 } 31796 31797 visitSafeKeyedRead(ast, context) { 31798 const obj = ast.receiver.visit(this); 31799 const key = ast.key.visit(this); 31800 31801 if (obj !== ast.receiver || key !== ast.key) { 31802 return new SafeKeyedRead(ast.span, ast.sourceSpan, obj, key); 31803 } 31804 31805 return ast; 31806 } 31807 31808} // Bindings 31809 31810 31811class ParsedProperty { 31812 constructor(name, expression, type, sourceSpan, keySpan, valueSpan) { 31813 this.name = name; 31814 this.expression = expression; 31815 this.type = type; 31816 this.sourceSpan = sourceSpan; 31817 this.keySpan = keySpan; 31818 this.valueSpan = valueSpan; 31819 this.isLiteral = this.type === ParsedPropertyType.LITERAL_ATTR; 31820 this.isAnimation = this.type === ParsedPropertyType.ANIMATION; 31821 } 31822 31823} 31824 31825var ParsedPropertyType; 31826 31827(function (ParsedPropertyType) { 31828 ParsedPropertyType[ParsedPropertyType["DEFAULT"] = 0] = "DEFAULT"; 31829 ParsedPropertyType[ParsedPropertyType["LITERAL_ATTR"] = 1] = "LITERAL_ATTR"; 31830 ParsedPropertyType[ParsedPropertyType["ANIMATION"] = 2] = "ANIMATION"; 31831})(ParsedPropertyType || (ParsedPropertyType = {})); 31832 31833class ParsedEvent { 31834 // Regular events have a target 31835 // Animation events have a phase 31836 constructor(name, targetOrPhase, type, handler, sourceSpan, handlerSpan, keySpan) { 31837 this.name = name; 31838 this.targetOrPhase = targetOrPhase; 31839 this.type = type; 31840 this.handler = handler; 31841 this.sourceSpan = sourceSpan; 31842 this.handlerSpan = handlerSpan; 31843 this.keySpan = keySpan; 31844 } 31845 31846} 31847/** 31848 * ParsedVariable represents a variable declaration in a microsyntax expression. 31849 */ 31850 31851 31852class ParsedVariable { 31853 constructor(name, value, sourceSpan, keySpan, valueSpan) { 31854 this.name = name; 31855 this.value = value; 31856 this.sourceSpan = sourceSpan; 31857 this.keySpan = keySpan; 31858 this.valueSpan = valueSpan; 31859 } 31860 31861} 31862 31863class BoundElementProperty { 31864 constructor(name, type, securityContext, value, unit, sourceSpan, keySpan, valueSpan) { 31865 this.name = name; 31866 this.type = type; 31867 this.securityContext = securityContext; 31868 this.value = value; 31869 this.unit = unit; 31870 this.sourceSpan = sourceSpan; 31871 this.keySpan = keySpan; 31872 this.valueSpan = valueSpan; 31873 } 31874 31875} 31876/** 31877 * @license 31878 * Copyright Google LLC All Rights Reserved. 31879 * 31880 * Use of this source code is governed by an MIT-style license that can be 31881 * found in the LICENSE file at https://angular.io/license 31882 */ 31883 31884 31885class EventHandlerVars {} 31886 31887EventHandlerVars.event = variable('$event'); 31888/** 31889 * Converts the given expression AST into an executable output AST, assuming the expression is 31890 * used in an action binding (e.g. an event handler). 31891 */ 31892 31893function convertActionBinding(localResolver, implicitReceiver, action, bindingId, baseSourceSpan, implicitReceiverAccesses, globals) { 31894 if (!localResolver) { 31895 localResolver = new DefaultLocalResolver(globals); 31896 } 31897
31898 const actionWithoutBuiltins = convertPropertyBindingBuiltins({ 31899 createLiteralArrayConverter: argCount => { 31900 // Note: no caching for literal arrays in actions. 31901 return args => literalArr(args); 31902 }, 31903 createLiteralMapConverter: keys => { 31904 // Note: no caching for literal maps in actions. 31905 return values => { 31906 const entries = keys.map((k, i) => ({ 31907 key: k.key, 31908 value: values[i], 31909 quoted: k.quoted 31910 })); 31911 return literalMap(entries); 31912 }; 31913 }, 31914 createPipeConverter: name => { 31915 throw new Error(`Illegal State: Actions are not allowed to contain pipes. Pipe: ${name}`); 31916 } 31917 }, action); 31918 const visitor = new _AstToIrVisitor(localResolver, implicitReceiver, bindingId, 31919 /* supportsInterpolation */ 31920 false, baseSourceSpan, implicitReceiverAccesses); 31921 const actionStmts = []; 31922 flattenStatements(actionWithoutBuiltins.visit(visitor, _Mode.Statement), actionStmts); 31923 prependTemporaryDecls(visitor.temporaryCount, bindingId, actionStmts); 31924 31925 if (visitor.usesImplicitReceiver) { 31926 localResolver.notifyImplicitReceiverUse(); 31927 } 31928 31929 const lastIndex = actionStmts.length - 1; 31930 31931 if (lastIndex >= 0) { 31932 const lastStatement = actionStmts[lastIndex]; // Ensure that the value of the last expression statement is returned 31933 31934 if (lastStatement instanceof ExpressionStatement) {
31935 actionStmts[lastIndex] = new ReturnStatement(lastStatement.expr); 31936 } 31937 } 31938 31939 return actionStmts; 31940} 31941 31942function convertPropertyBindingBuiltins(converterFactory, ast) { 31943 return convertBuiltins(converterFactory, ast); 31944} 31945 31946class ConvertPropertyBindingResult { 31947 constructor(stmts, currValExpr) { 31948 this.stmts = stmts; 31949 this.currValExpr = currValExpr; 31950 } 31951 31952} 31953/** 31954 * Converts the given expression AST into an executable output AST, assuming the expression 31955 * is used in property binding. The expression has to be preprocessed via 31956 * `convertPropertyBindingBuiltins`. 31957 */ 31958 31959 31960function convertPropertyBinding(localResolver, implicitReceiver, expressionWithoutBuiltins, bindingId) { 31961 if (!localResolver) { 31962 localResolver = new DefaultLocalResolver(); 31963 } 31964 31965 const visitor = new _AstToIrVisitor(localResolver, implicitReceiver, bindingId, 31966 /* supportsInterpolation */ 31967 false); 31968 const outputExpr = expressionWithoutBuiltins.visit(visitor, _Mode.Expression); 31969 const stmts = getStatementsFromVisitor(visitor, bindingId); 31970 31971 if (visitor.usesImplicitReceiver) { 31972 localResolver.notifyImplicitReceiverUse(); 31973 } 31974 31975 return new ConvertPropertyBindingResult(stmts, outputExpr); 31976} 31977/** 31978 * Given some expression, such as a binding or interpolation expression, and a context expression to 31979 * look values up on, visit each facet of the given expression resolving values from the context 31980 * expression such that a list of arguments can be derived from the found values that can be used as 31981 * arguments to an external update instruction. 31982 * 31983 * @param localResolver The resolver to use to look up expressions by name appropriately 31984 * @param contextVariableExpression The expression representing the context variable used to create 31985 * the final argument expressions 31986 * @param expressionWithArgumentsToExtract The expression to visit to figure out what values need to 31987 * be resolved and what arguments list to build. 31988 * @param bindingId A name prefix used to create temporary variable names if they're needed for the 31989 * arguments generated 31990 * @returns An array of expressions that can be passed as arguments to instruction expressions like 31991 * `o.importExpr(R3.propertyInterpolate).callFn(result)` 31992 */ 31993 31994 31995function convertUpdateArguments(localResolver, contextVariableExpression, expressionWithArgumentsToExtract, bindingId) { 31996 const visitor = new _AstToIrVisitor(localResolver, contextVariableExpression, bindingId, 31997 /* supportsInterpolation */ 31998 true); 31999 const outputExpr = visitor.visitInterpolation(expressionWithArgumentsToExtract, _Mode.Expression); 32000 32001 if (visitor.usesImplicitReceiver) { 32002 localResolver.notifyImplicitReceiverUse(); 32003 } 32004 32005 const stmts = getStatementsFromVisitor(visitor, bindingId); 32006 const args = outputExpr.args; 32007 return { 32008 stmts, 32009 args 32010 }; 32011} 32012 32013function getStatementsFromVisitor(visitor, bindingId) { 32014 const stmts = []; 32015 32016 for (let i = 0; i < visitor.temporaryCount; i++) { 32017 stmts.push(temporaryDeclaration(bindingId, i)); 32018 } 32019 32020 return stmts; 32021} 32022 32023function convertBuiltins(converterFactory, ast) { 32024 const visitor = new _BuiltinAstConverter(converterFactory); 32025 return ast.visit(visitor); 32026} 32027 32028function temporaryName(bindingId, temporaryNumber) { 32029 return `tmp_${bindingId}_${temporaryNumber}`; 32030} 32031 32032function temporaryDeclaration(bindingId, temporaryNumber) { 32033 return new DeclareVarStmt(temporaryName(bindingId, temporaryNumber)); 32034} 32035 32036function prependTemporaryDecls(temporaryCount, bindingId, statements) { 32037 for (let i = temporaryCount - 1; i >= 0; i--) { 32038 statements.unshift(temporaryDeclaration(bindingId, i)); 32039 } 32040} 32041 32042var _Mode; 32043 32044(function (_Mode) { 32045 _Mode[_Mode["Statement"] = 0] = "Statement"; 32046 _Mode[_Mode["Expression"] = 1] = "Expression"; 32047})(_Mode || (_Mode = {})); 32048 32049function ensureStatementMode(mode, ast) { 32050 if (mode !== _Mode.Statement) { 32051 throw new Error(`Expected a statement, but saw ${ast}`); 32052 } 32053} 32054 32055function ensureExpressionMode(mode, ast) { 32056 if (mode !== _Mode.Expression) { 32057 throw new Error(`Expected an expression, but saw ${ast}`); 32058 } 32059} 32060 32061function convertToStatementIfNeeded(mode, expr) { 32062 if (mode === _Mode.Statement) { 32063 return expr.toStmt(); 32064 } else { 32065 return expr; 32066 } 32067} 32068 32069class _BuiltinAstConverter extends AstTransformer { 32070 constructor(_converterFactory) { 32071 super(); 32072 this._converterFactory = _converterFactory; 32073 } 32074 32075 visitPipe(ast, context) { 32076 const args = [ast.exp, ...ast.args].map(ast => ast.visit(this, context)); 32077 return new BuiltinFunctionCall(ast.span, ast.sourceSpan, args, this._converterFactory.createPipeConverter(ast.name, args.length)); 32078 } 32079 32080 visitLiteralArray(ast, context) { 32081 const args = ast.expressions.map(ast => ast.visit(this, context)); 32082 return new BuiltinFunctionCall(ast.span, ast.sourceSpan, args, this._converterFactory.createLiteralArrayConverter(ast.expressions.length)); 32083 } 32084 32085 visitLiteralMap(ast, context) { 32086 const args = ast.values.map(ast => ast.visit(this, context)); 32087 return new BuiltinFunctionCall(ast.span, ast.sourceSpan, args, this._converterFactory.createLiteralMapConverter(ast.keys)); 32088 } 32089 32090} 32091 32092class _AstToIrVisitor { 32093 constructor(_localResolver, _implicitReceiver, bindingId, supportsInterpolation, baseSourceSpan, implicitReceiverAccesses) { 32094 this._localResolver = _localResolver;
32095 this._implicitReceiver = _implicitReceiver; 32096 this.bindingId = bindingId; 32097 this.supportsInterpolation = supportsInterpolation; 32098 this.baseSourceSpan = baseSourceSpan; 32099 this.implicitReceiverAccesses = implicitReceiverAccesses; 32100 this._nodeMap = new Map(); 32101 this._resultMap = new Map(); 32102 this._currentTemporary = 0; 32103 this.temporaryCount = 0; 32104 this.usesImplicitReceiver = false; 32105 } 32106 32107 visitUnary(ast, mode) { 32108 let op; 32109 32110 switch (ast.operator) { 32111 case '+': 32112 op = UnaryOperator.Plus; 32113 break; 32114 32115 case '-': 32116 op = UnaryOperator.Minus; 32117 break; 32118 32119 default: 32120 throw new Error(`Unsupported operator ${ast.operator}`); 32121 } 32122 32123 return convertToStatementIfNeeded(mode, new UnaryOperatorExpr(op, this._visit(ast.expr, _Mode.Expression), undefined, this.convertSourceSpan(ast.span))); 32124 } 32125 32126 visitBinary(ast, mode) { 32127 let op; 32128 32129 switch (ast.operation) { 32130 case '+': 32131 op = BinaryOperator.Plus; 32132 break; 32133 32134 case '-': 32135 op = BinaryOperator.Minus; 32136 break; 32137 32138 case '*': 32139 op = BinaryOperator.Multiply; 32140 break; 32141 32142 case '/': 32143 op = BinaryOperator.Divide; 32144 break; 32145 32146 case '%': 32147 op = BinaryOperator.Modulo; 32148 break; 32149 32150 case '&&': 32151 op = BinaryOperator.And; 32152 break; 32153 32154 case '||': 32155 op = BinaryOperator.Or; 32156 break; 32157 32158 case '==': 32159 op = BinaryOperator.Equals; 32160 break; 32161 32162 case '!=': 32163 op = BinaryOperator.NotEquals; 32164 break; 32165 32166 case '===': 32167 op = BinaryOperator.Identical; 32168 break; 32169 32170 case '!==': 32171 op = BinaryOperator.NotIdentical; 32172 break; 32173 32174 case '<': 32175 op = BinaryOperator.Lower; 32176 break; 32177 32178 case '>': 32179 op = BinaryOperator.Bigger; 32180 break; 32181 32182 case '<=': 32183 op = BinaryOperator.LowerEquals; 32184 break; 32185 32186 case '>=': 32187 op = BinaryOperator.BiggerEquals; 32188 break; 32189 32190 case '??': 32191 return this.convertNullishCoalesce(ast, mode); 32192 32193 default: 32194 throw new Error(`Unsupported operation ${ast.operation}`); 32195 } 32196 32197 return convertToStatementIfNeeded(mode, new BinaryOperatorExpr(op, this._visit(ast.left, _Mode.Expression), this._visit(ast.right, _Mode.Expression), undefined, this.convertSourceSpan(ast.span))); 32198 } 32199 32200 visitChain(ast, mode) { 32201 ensureStatementMode(mode, ast); 32202 return this.visitAll(ast.expressions, mode); 32203 } 32204 32205 visitConditional(ast, mode) { 32206 const value = this._visit(ast.condition, _Mode.Expression); 32207 32208 return convertToStatementIfNeeded(mode, value.conditional(this._visit(ast.trueExp, _Mode.Expression), this._visit(ast.falseExp, _Mode.Expression), this.convertSourceSpan(ast.span))); 32209 } 32210 32211 visitPipe(ast, mode) { 32212 throw new Error(`Illegal state: Pipes should have been converted into functions. Pipe: ${ast.name}`); 32213 } 32214 32215 visitImplicitReceiver(ast, mode) { 32216 ensureExpressionMode(mode, ast); 32217 this.usesImplicitReceiver = true; 32218 return this._implicitReceiver; 32219 } 32220 32221 visitThisReceiver(ast, mode) { 32222 return this.visitImplicitReceiver(ast, mode); 32223 } 32224 32225 visitInterpolation(ast, mode) { 32226 if (!this.supportsInterpolation) { 32227 throw new Error('Unexpected interpolation'); 32228 } 32229 32230 ensureExpressionMode(mode, ast); 32231 let args = []; 32232 32233 for (let i = 0; i < ast.strings.length - 1; i++) { 32234 args.push(literal(ast.strings[i])); 32235 args.push(this._visit(ast.expressions[i], _Mode.Expression)); 32236 } 32237 32238 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 32239 // args returned to just the value, because we're going to pass it to a special instruction. 32240 32241 const strings = ast.strings; 32242 32243 if (strings.length === 2 && strings[0] === '' && strings[1] === '') { 32244 // Single argument interpolate instructions. 32245 args = [args[1]]; 32246 } else if (ast.expressions.length >= 9) { 32247 // 9 or more arguments must be passed to the `interpolateV`-style instructions, which accept 32248 // an array of arguments 32249 args = [literalArr(args)]; 32250 } 32251 32252 return new InterpolationExpression(args); 32253 } 32254 32255 visitKeyedRead(ast, mode) { 32256 const leftMostSafe = this.leftMostSafeNode(ast); 32257 32258 if (leftMostSafe) { 32259 return this.convertSafeAccess(ast, leftMostSafe, mode); 32260 } else { 32261 return convertToStatementIfNeeded(mode, this._visit(ast.receiver, _Mode.Expression).key(this._visit(ast.key, _Mode.Expression))); 32262 } 32263 } 32264 32265 visitKeyedWrite(ast, mode) { 32266 const obj = this._visit(ast.receiver, _Mode.Expression); 32267
32268 const key = this._visit(ast.key, _Mode.Expression); 32269 32270 const value = this._visit(ast.value, _Mode.Expression); 32271 32272 if (obj === this._implicitReceiver) { 32273 this._localResolver.maybeRestoreView(); 32274 } 32275 32276 return convertToStatementIfNeeded(mode, obj.key(key).set(value)); 32277 } 32278 32279 visitLiteralArray(ast, mode) { 32280 throw new Error(`Illegal State: literal arrays should have been converted into functions`); 32281 } 32282 32283 visitLiteralMap(ast, mode) { 32284 throw new Error(`Illegal State: literal maps should have been converted into functions`); 32285 } 32286 32287 visitLiteralPrimitive(ast, mode) { 32288 // For literal values of null, undefined, true, or false allow type interference 32289 // to infer the type. 32290 const type = ast.value === null || ast.value === undefined || ast.value === true || ast.value === true ? INFERRED_TYPE : undefined; 32291 return convertToStatementIfNeeded(mode, literal(ast.value, type, this.convertSourceSpan(ast.span))); 32292 } 32293 32294 _getLocal(name, receiver) { 32295 if (this._localResolver.globals?.has(name) && receiver instanceof ThisReceiver) { 32296 return null; 32297 } 32298 32299 return this._localResolver.getLocal(name); 32300 } 32301 32302 visitPrefixNot(ast, mode) { 32303 return convertToStatementIfNeeded(mode, not(this._visit(ast.expression, _Mode.Expression))); 32304 } 32305 32306 visitNonNullAssert(ast, mode) { 32307 return convertToStatementIfNeeded(mode, this._visit(ast.expression, _Mode.Expression)); 32308 } 32309 32310 visitPropertyRead(ast, mode) { 32311 const leftMostSafe = this.leftMostSafeNode(ast); 32312 32313 if (leftMostSafe) { 32314 return this.convertSafeAccess(ast, leftMostSafe, mode); 32315 } else { 32316 let result = null; 32317 const prevUsesImplicitReceiver = this.usesImplicitReceiver; 32318 32319 const receiver = this._visit(ast.receiver, _Mode.Expression); 32320 32321 if (receiver === this._implicitReceiver) { 32322 result = this._getLocal(ast.name, ast.receiver); 32323 32324 if (result) { 32325 // Restore the previous "usesImplicitReceiver" state since the implicit 32326 // receiver has been replaced with a resolved local expression. 32327 this.usesImplicitReceiver = prevUsesImplicitReceiver; 32328 this.addImplicitReceiverAccess(ast.name); 32329 } 32330 } 32331 32332 if (result == null) { 32333 result = receiver.prop(ast.name, this.convertSourceSpan(ast.span)); 32334 } 32335 32336 return convertToStatementIfNeeded(mode, result); 32337 } 32338 } 32339 32340 visitPropertyWrite(ast, mode) { 32341 const receiver = this._visit(ast.receiver, _Mode.Expression); 32342 32343 const prevUsesImplicitReceiver = this.usesImplicitReceiver; 32344 let varExpr = null; 32345 32346 if (receiver === this._implicitReceiver) { 32347 const localExpr = this._getLocal(ast.name, ast.receiver); 32348 32349 if (localExpr) { 32350 if (localExpr instanceof ReadPropExpr) { 32351 // If the local variable is a property read expression, it's a reference 32352 // to a 'context.property' value and will be used as the target of the 32353 // write expression. 32354 varExpr = localExpr; // Restore the previous "usesImplicitReceiver" state since the implicit 32355 // receiver has been replaced with a resolved local expression. 32356 32357 this.usesImplicitReceiver = prevUsesImplicitReceiver; 32358 this.addImplicitReceiverAccess(ast.name); 32359 } else { 32360 // Otherwise it's an error. 32361 const receiver = ast.name; 32362 const value = ast.value instanceof PropertyRead ? ast.value.name : undefined; 32363 throw new Error(`Cannot assign value "${value}" to template variable "${receiver}". Template variables are read-only.`); 32364 } 32365 } 32366 } // If no local expression could be produced, use the original receiver's 32367 // property as the target. 32368 32369 32370 if (varExpr === null) { 32371 varExpr = receiver.prop(ast.name, this.convertSourceSpan(ast.span)); 32372 } 32373 32374 return convertToStatementIfNeeded(mode, varExpr.set(this._visit(ast.value, _Mode.Expression))); 32375 } 32376 32377 visitSafePropertyRead(ast, mode) { 32378 return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode); 32379 } 32380 32381 visitSafeKeyedRead(ast, mode) { 32382 return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode); 32383 } 32384 32385 visitAll(asts, mode) { 32386 return asts.map(ast => this._visit(ast, mode)); 32387 } 32388 32389 visitCall(ast, mode) { 32390 const leftMostSafe = this.leftMostSafeNode(ast); 32391 32392 if (leftMostSafe) { 32393 return this.convertSafeAccess(ast, leftMostSafe, mode); 32394 } 32395 32396 const convertedArgs = this.visitAll(ast.args, _Mode.Expression); 32397
32398 if (ast instanceof BuiltinFunctionCall) { 32399 return convertToStatementIfNeeded(mode, ast.converter(convertedArgs)); 32400 } 32401 32402 const receiver = ast.receiver; 32403 32404 if (receiver instanceof PropertyRead && receiver.receiver instanceof ImplicitReceiver && !(receiver.receiver instanceof ThisReceiver) && receiver.name === '$any') { 32405 if (convertedArgs.length !== 1) { 32406 throw new Error(`Invalid call to $any, expected 1 argument but received ${convertedArgs.length || 'none'}`); 32407 } 32408 32409 return convertToStatementIfNeeded(mode, convertedArgs[0]); 32410 } 32411 32412 const call = this._visit(receiver, _Mode.Expression).callFn(convertedArgs, this.convertSourceSpan(ast.span)); 32413 32414 return convertToStatementIfNeeded(mode, call); 32415 } 32416 32417 visitSafeCall(ast, mode) { 32418 return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode); 32419 } 32420 32421 _visit(ast, mode) { 32422 const result = this._resultMap.get(ast); 32423 32424 if (result) return result; 32425 return (this._nodeMap.get(ast) || ast).visit(this, mode); 32426 } 32427 32428 convertSafeAccess(ast, leftMostSafe, mode) { 32429 // If the expression contains a safe access node on the left it needs to be converted to 32430 // an expression that guards the access to the member by checking the receiver for blank. As 32431 // execution proceeds from left to right, the left most part of the expression must be guarded 32432 // first but, because member access is left associative, the right side of the expression is at 32433 // the top of the AST. The desired result requires lifting a copy of the left part of the 32434 // expression up to test it for blank before generating the unguarded version. 32435 // Consider, for example the following expression: a?.b.c?.d.e 32436 // This results in the ast: 32437 // . 32438 // / \ 32439 // ?. e 32440 // / \ 32441 // . d 32442 // / \ 32443 // ?. c 32444 // / \ 32445 // a b 32446 // The following tree should be generated: 32447 // 32448 // /---- ? ----\ 32449 // / | \ 32450 // a /--- ? ---\ null 32451 // / | \ 32452 // . . null 32453 // / \ / \ 32454 // . c . e 32455 // / \ / \ 32456 // a b . d 32457 // / \ 32458 // . c 32459 // / \ 32460 // a b 32461 // 32462 // Notice that the first guard condition is the left hand of the left most safe access node 32463 // which comes in as leftMostSafe to this routine. 32464 let guardedExpression = this._visit(leftMostSafe.receiver, _Mode.Expression); 32465 32466 let temporary = undefined; 32467 32468 if (this.needsTemporaryInSafeAccess(leftMostSafe.receiver)) { 32469 // If the expression has method calls or pipes then we need to save the result into a 32470 // temporary variable to avoid calling stateful or impure code more than once. 32471 temporary = this.allocateTemporary(); // Preserve the result in the temporary variable 32472 32473 guardedExpression = temporary.set(guardedExpression); // Ensure all further references to the guarded expression refer to the temporary instead. 32474 32475 this._resultMap.set(leftMostSafe.receiver, temporary); 32476 } 32477 32478 const condition = guardedExpression.isBlank(); // Convert the ast to an unguarded access to the receiver's member. The map will substitute 32479 // leftMostNode with its unguarded version in the call to `this.visit()`. 32480 32481 if (leftMostSafe instanceof SafeCall) { 32482 this._nodeMap.set(leftMostSafe, new Call(leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.receiver, leftMostSafe.args, leftMostSafe.argumentSpan)); 32483 } else if (leftMostSafe instanceof SafeKeyedRead) { 32484 this._nodeMap.set(leftMostSafe, new KeyedRead(leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.receiver, leftMostSafe.key)); 32485 } else { 32486 this._nodeMap.set(leftMostSafe, new PropertyRead(leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.nameSpan, leftMostSafe.receiver, leftMostSafe.name)); 32487 } // Recursively convert the node now without the guarded member access. 32488 32489 32490 const access = this._visit(ast, _Mode.Expression); // Remove the mapping. This is not strictly required as the converter only traverses each node 32491 // once but is safer if the conversion is changed to traverse the nodes more than once. 32492 32493 32494 this._nodeMap.delete(leftMostSafe); // If we allocated a temporary, release it. 32495 32496 32497 if (temporary) { 32498 this.releaseTemporary(temporary); 32499 } // Produce the conditional 32500 32501 32502 return convertToStatementIfNeeded(mode, condition.conditional(NULL_EXPR, access)); 32503 } 32504 32505 convertNullishCoalesce(ast, mode) { 32506 const left = this._visit(ast.left, _Mode.Expression); 32507 32508 const right = this._visit(ast.right, _Mode.Expression); 32509 32510 const temporary = this.allocateTemporary(); 32511 this.releaseTemporary(temporary); // Generate the following expression. It is identical to how TS 32512 // transpiles binary expressions with a nullish coalescing operator. 32513 // let temp; 32514 // (temp = a) !== null && temp !== undefined ? temp : b; 32515 32516 return convertToStatementIfNeeded(mode, temporary.set(left).notIdentical(NULL_EXPR).and(temporary.notIdentical(literal(undefined))).conditional(temporary, right)); 32517 } // Given an expression of the form a?.b.c?.d.e then the left most safe node is 32518 // the (a?.b). The . and ?. are left associative thus can be rewritten as: 32519 // ((((a?.c).b).c)?.d).e. This returns the most deeply nested safe read or 32520 // safe method call as this needs to be transformed initially to: 32521 // a == null ? null : a.c.b.c?.d.e 32522 // then to: 32523 // a == null ? null : a.b.c == null ? null : a.b.c.d.e 32524 32525 32526 leftMostSafeNode(ast) { 32527 const visit = (visitor, ast) => { 32528 return (this._nodeMap.get(ast) || ast).visit(visitor); 32529 }; 32530 32531 return ast.visit({ 32532 visitUnary(ast) { 32533 return null; 32534 }, 32535 32536 visitBinary(ast) { 32537 return null; 32538 }, 32539
32540 visitChain(ast) { 32541 return null; 32542 }, 32543 32544 visitConditional(ast) { 32545 return null; 32546 }, 32547 32548 visitCall(ast) { 32549 return visit(this, ast.receiver); 32550 }, 32551 32552 visitSafeCall(ast) { 32553 return visit(this, ast.receiver) || ast; 32554 }, 32555 32556 visitImplicitReceiver(ast) { 32557 return null; 32558 }, 32559 32560 visitThisReceiver(ast) { 32561 return null; 32562 }, 32563 32564 visitInterpolation(ast) { 32565 return null; 32566 }, 32567 32568 visitKeyedRead(ast) { 32569 return visit(this, ast.receiver); 32570 }, 32571 32572 visitKeyedWrite(ast) { 32573 return null; 32574 }, 32575 32576 visitLiteralArray(ast) { 32577 return null; 32578 }, 32579 32580 visitLiteralMap(ast) { 32581 return null; 32582 }, 32583 32584 visitLiteralPrimitive(ast) { 32585 return null; 32586 }, 32587 32588 visitPipe(ast) { 32589 return null; 32590 }, 32591 32592 visitPrefixNot(ast) { 32593 return null; 32594 }, 32595 32596 visitNonNullAssert(ast) { 32597 return null; 32598 }, 32599 32600 visitPropertyRead(ast) { 32601 return visit(this, ast.receiver); 32602 }, 32603 32604 visitPropertyWrite(ast) { 32605 return null; 32606 }, 32607 32608 visitSafePropertyRead(ast) { 32609 return visit(this, ast.receiver) || ast; 32610 }, 32611 32612 visitSafeKeyedRead(ast) { 32613 return visit(this, ast.receiver) || ast; 32614 } 32615 32616 }); 32617 } // Returns true of the AST includes a method or a pipe indicating that, if the 32618 // expression is used as the target of a safe property or method access then 32619 // the expression should be stored into a temporary variable. 32620 32621 32622 needsTemporaryInSafeAccess(ast) { 32623 const visit = (visitor, ast) => { 32624 return ast && (this._nodeMap.get(ast) || ast).visit(visitor); 32625 }; 32626 32627 const visitSome = (visitor, ast) => { 32628 return ast.some(ast => visit(visitor, ast)); 32629 }; 32630 32631 return ast.visit({ 32632 visitUnary(ast) { 32633 return visit(this, ast.expr); 32634 }, 32635 32636 visitBinary(ast) { 32637 return visit(this, ast.left) || visit(this, ast.right); 32638 }, 32639 32640 visitChain(ast) { 32641 return false; 32642 }, 32643 32644 visitConditional(ast) { 32645 return visit(this, ast.condition) || visit(this, ast.trueExp) || visit(this, ast.falseExp); 32646 }, 32647 32648 visitCall(ast) { 32649 return true; 32650 }, 32651 32652 visitSafeCall(ast) { 32653 return true; 32654 }, 32655 32656 visitImplicitReceiver(ast) { 32657 return false; 32658 }, 32659 32660 visitThisReceiver(ast) { 32661 return false; 32662 }, 32663 32664 visitInterpolation(ast) { 32665 return visitSome(this, ast.expressions); 32666 }, 32667 32668 visitKeyedRead(ast) { 32669 return false; 32670 }, 32671 32672 visitKeyedWrite(ast) { 32673 return false; 32674 }, 32675 32676 visitLiteralArray(ast) { 32677 return true; 32678 }, 32679 32680 visitLiteralMap(ast) { 32681 return true; 32682 }, 32683 32684 visitLiteralPrimitive(ast) { 32685 return false; 32686 }, 32687 32688 visitPipe(ast) { 32689 return true; 32690 }, 32691 32692 visitPrefixNot(ast) { 32693 return visit(this, ast.expression); 32694 }, 32695 32696 visitNonNullAssert(ast) { 32697 return visit(this, ast.expression); 32698 }, 32699 32700 visitPropertyRead(ast) { 32701 return false; 32702 }, 32703 32704 visitPropertyWrite(ast) { 32705 return false; 32706 }, 32707 32708 visitSafePropertyRead(ast) { 32709 return false; 32710 }, 32711 32712 visitSafeKeyedRead(ast) { 32713 return false; 32714 } 32715 32716 }); 32717 } 32718 32719 allocateTemporary() { 32720 const tempNumber = this._currentTemporary++; 32721 this.temporaryCount = Math.max(this._currentTemporary, this.temporaryCount); 32722 return new ReadVarExpr(temporaryName(this.bindingId, tempNumber)); 32723 } 32724 32725 releaseTemporary(temporary) { 32726 this._currentTemporary--; 32727 32728 if (temporary.name != temporaryName(this.bindingId, this._currentTemporary)) { 32729 throw new Error(`Temporary ${temporary.name} released out of order`); 32730 } 32731 } 32732 /** 32733 * Creates an absolute `ParseSourceSpan` from the relative `ParseSpan`. 32734 * 32735 * `ParseSpan` objects are relative to the start of the expression. 32736 * This method converts these to full `ParseSourceSpan` objects that 32737 * show where the span is within the overall source file. 32738 * 32739 * @param span the relative span to convert. 32740 * @returns a `ParseSourceSpan` for the given span or null if no 32741 * `baseSourceSpan` was provided to this class. 32742 */ 32743 32744 32745 convertSourceSpan(span) { 32746 if (this.baseSourceSpan) { 32747 const start = this.baseSourceSpan.start.moveBy(span.start); 32748 const end = this.baseSourceSpan.start.moveBy(span.end); 32749 const fullStart = this.baseSourceSpan.fullStart.moveBy(span.start); 32750 return new ParseSourceSpan(start, end, fullStart); 32751 } else { 32752 return null; 32753 } 32754 } 32755 /** Adds the name of an AST to the list of implicit receiver accesses. */ 32756 32757 32758 addImplicitReceiverAccess(name) {
32759 if (this.implicitReceiverAccesses) { 32760 this.implicitReceiverAccesses.add(name); 32761 } 32762 } 32763 32764} 32765 32766function flattenStatements(arg, output) { 32767 if (Array.isArray(arg)) { 32768 arg.forEach(entry => flattenStatements(entry, output)); 32769 } else { 32770 output.push(arg); 32771 } 32772} 32773 32774function unsupported() { 32775 throw new Error('Unsupported operation'); 32776} 32777 32778class InterpolationExpression extends Expression { 32779 constructor(args) { 32780 super(null, null); 32781 this.args = args; 32782 this.isConstant = unsupported; 32783 this.isEquivalent = unsupported; 32784 this.visitExpression = unsupported; 32785 } 32786 32787} 32788 32789class DefaultLocalResolver { 32790 constructor(globals) { 32791 this.globals = globals; 32792 } 32793 32794 notifyImplicitReceiverUse() {} 32795 32796 maybeRestoreView() {} 32797 32798 getLocal(name) { 32799 if (name === EventHandlerVars.event.name) { 32800 return EventHandlerVars.event; 32801 } 32802 32803 return null; 32804 } 32805 32806} 32807 32808class BuiltinFunctionCall extends Call { 32809 constructor(span, sourceSpan, args, converter) { 32810 super(span, sourceSpan, new EmptyExpr(span, sourceSpan), args, null); 32811 this.converter = converter; 32812 } 32813 32814} 32815/** 32816 * @license 32817 * Copyright Google LLC All Rights Reserved. 32818 * 32819 * Use of this source code is governed by an MIT-style license that can be 32820 * found in the LICENSE file at https://angular.io/license 32821 */ 32822 32823/** 32824 * This file is a port of shadowCSS from webcomponents.js to TypeScript. 32825 * 32826 * Please make sure to keep to edits in sync with the source file. 32827 * 32828 * Source: 32829 * https://github.com/webcomponents/webcomponentsjs/blob/4efecd7e0e/src/ShadowCSS/ShadowCSS.js 32830 * 32831 * The original file level comment is reproduced below 32832 */ 32833 32834/* 32835 This is a limited shim for ShadowDOM css styling. 32836 https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#styles 32837 32838 The intention here is to support only the styling features which can be 32839 relatively simply implemented. The goal is to allow users to avoid the 32840 most obvious pitfalls and do so without compromising performance significantly. 32841 For ShadowDOM styling that's not covered here, a set of best practices 32842 can be provided that should allow users to accomplish more complex styling. 32843 32844 The following is a list of specific ShadowDOM styling features and a brief 32845 discussion of the approach used to shim. 32846 32847 Shimmed features: 32848 32849 * :host, :host-context: ShadowDOM allows styling of the shadowRoot's host 32850 element using the :host rule. To shim this feature, the :host styles are 32851 reformatted and prefixed with a given scope name and promoted to a 32852 document level stylesheet. 32853 For example, given a scope name of .foo, a rule like this: 32854 32855 :host { 32856 background: red; 32857 } 32858 } 32859 32860 becomes: 32861 32862 .foo { 32863 background: red; 32864 } 32865 32866 * encapsulation: Styles defined within ShadowDOM, apply only to 32867 dom inside the ShadowDOM. Polymer uses one of two techniques to implement 32868 this feature. 32869 32870 By default, rules are prefixed with the host element tag name 32871 as a descendant selector. This ensures styling does not leak out of the 'top' 32872 of the element's ShadowDOM. For example, 32873 32874 div { 32875 font-weight: bold; 32876 } 32877 32878 becomes: 32879 32880 x-foo div { 32881 font-weight: bold; 32882 } 32883 32884 becomes: 32885 32886 32887 Alternatively, if WebComponents.ShadowCSS.strictStyling is set to true then 32888 selectors are scoped by adding an attribute selector suffix to each 32889 simple selector that contains the host element tag name. Each element 32890 in the element's ShadowDOM template is also given the scope attribute. 32891 Thus, these rules match only elements that have the scope attribute. 32892 For example, given a scope name of x-foo, a rule like this: 32893 32894 div { 32895 font-weight: bold; 32896 } 32897 32898 becomes: 32899 32900 div[x-foo] { 32901 font-weight: bold; 32902 } 32903 32904 Note that elements that are dynamically added to a scope must have the scope 32905 selector added to them manually. 32906 32907 * upper/lower bound encapsulation: Styles which are defined outside a 32908 shadowRoot should not cross the ShadowDOM boundary and should not apply 32909 inside a shadowRoot. 32910 32911 This styling behavior is not emulated. Some possible ways to do this that 32912 were rejected due to complexity and/or performance concerns include: (1) reset 32913 every possible property for every possible selector for a given scope name; 32914 (2) re-implement css in javascript. 32915 32916 As an alternative, users should make sure to use selectors 32917 specific to the scope in which they are working. 32918 32919 * ::distributed: This behavior is not emulated. It's often not necessary 32920 to style the contents of a specific insertion point and instead, descendants 32921 of the host element can be styled selectively. Users can also create an 32922 extra node around an insertion point and style that node's contents 32923 via descendent selectors. For example, with a shadowRoot like this: 32924 32925 <style> 32926 ::content(div) { 32927 background: red; 32928 } 32929 </style> 32930 <content></content> 32931 32932 could become: 32933 32934 <style> 32935 / *@polyfill .content-container div * / 32936 ::content(div) { 32937 background: red; 32938 } 32939 </style> 32940 <div class="content-container"> 32941 <content></content> 32942 </div> 32943 32944 Note the use of @polyfill in the comment above a ShadowDOM specific style 32945 declaration. This is a directive to the styling shim to use the selector 32946 in comments in lieu of the next selector when running under polyfill. 32947*/ 32948 32949 32950class ShadowCss { 32951 constructor() { 32952 this.strictStyling = true; 32953 } 32954 /* 32955 * Shim some cssText with the given selector. Returns cssText that can 32956 * be included in the document via WebComponents.ShadowCSS.addCssToDocument(css). 32957 * 32958 * When strictStyling is true: 32959 * - selector is the attribute added to all elements inside the host, 32960 * - hostSelector is the attribute added to the host itself. 32961 */ 32962 32963 32964 shimCssText(cssText, selector, hostSelector = '') { 32965 const commentsWithHash = extractCommentsWithHash(cssText); 32966 cssText = stripComments(cssText); 32967 cssText = this._insertDirectives(cssText); 32968 32969 const scopedCssText = this._scopeCssText(cssText, selector, hostSelector); 32970 32971 return [scopedCssText, ...commentsWithHash].join('\n'); 32972 } 32973 32974 _insertDirectives(cssText) { 32975 cssText = this._insertPolyfillDirectivesInCssText(cssText); 32976 return this._insertPolyfillRulesInCssText(cssText); 32977 } 32978 /* 32979 * Process styles to convert native ShadowDOM rules that will trip 32980 * up the css parser; we rely on decorating the stylesheet with inert rules. 32981 * 32982 * For example, we convert this rule: 32983 * 32984 * polyfill-next-selector { content: ':host menu-item'; } 32985 * ::content menu-item { 32986 * 32987 * to this: 32988 * 32989 * scopeName menu-item { 32990 * 32991 **/ 32992 32993 32994 _insertPolyfillDirectivesInCssText(cssText) { 32995 // Difference with webcomponents.js: does not handle comments 32996 return cssText.replace(_cssContentNextSelectorRe, function (...m) { 32997 return m[2] + '{'; 32998 }); 32999 } 33000 /* 33001 * Process styles to add rules which will only apply under the polyfill 33002 * 33003 * For example, we convert this rule: 33004 * 33005 * polyfill-rule { 33006 * content: ':host menu-item'; 33007 * ... 33008 * } 33009 * 33010 * to this: 33011 * 33012 * scopeName menu-item {...} 33013 * 33014 **/ 33015 33016 33017 _insertPolyfillRulesInCssText(cssText) { 33018 // Difference with webcomponents.js: does not handle comments 33019 return cssText.replace(_cssContentRuleRe, (...m) => { 33020 const rule = m[0].replace(m[1], '').replace(m[2], ''); 33021 return m[4] + rule; 33022 }); 33023 } 33024 /* Ensure styles are scoped. Pseudo-scoping takes a rule like: 33025 * 33026 * .foo {... } 33027 * 33028 * and converts this to 33029 * 33030 * scopeName .foo { ... } 33031 */ 33032 33033 33034 _scopeCssText(cssText, scopeSelector, hostSelector) { 33035 const unscopedRules = this._extractUnscopedRulesFromCssText(cssText); // replace :host and :host-context -shadowcsshost and -shadowcsshost respectively 33036 33037 33038 cssText = this._insertPolyfillHostInCssText(cssText); 33039 cssText = this._convertColonHost(cssText); 33040 cssText = this._convertColonHostContext(cssText); 33041 cssText = this._convertShadowDOMSelectors(cssText); 33042 33043 if (scopeSelector) { 33044 cssText = this._scopeSelectors(cssText, scopeSelector, hostSelector); 33045 } 33046 33047 cssText = cssText + '\n' + unscopedRules; 33048 return cssText.trim(); 33049 } 33050 /* 33051 * Process styles to add rules which will only apply under the polyfill 33052 * and do not process via CSSOM. (CSSOM is destructive to rules on rare 33053 * occasions, e.g. -webkit-calc on Safari.) 33054 * For example, we convert this rule: 33055 * 33056 * @polyfill-unscoped-rule { 33057 * content: 'menu-item'; 33058 * ... } 33059 * 33060 * to this: 33061 * 33062 * menu-item {...} 33063 * 33064 **/ 33065 33066 33067 _extractUnscopedRulesFromCssText(cssText) { 33068 // Difference with webcomponents.js: does not handle comments 33069 let r = ''; 33070 let m; 33071 _cssContentUnscopedRuleRe.lastIndex = 0; 33072 33073 while ((m = _cssContentUnscopedRuleRe.exec(cssText)) !== null) { 33074 const rule = m[0].replace(m[2], '').replace(m[1], m[4]); 33075 r += rule + '\n\n'; 33076 } 33077 33078 return r; 33079 } 33080 /* 33081 * convert a rule like :host(.foo) > .bar { } 33082 * 33083 * to 33084 * 33085 * .foo<scopeName> > .bar 33086 */ 33087 33088 33089 _convertColonHost(cssText) { 33090 return cssText.replace(_cssColonHostRe, (_, hostSelectors, otherSelectors) => { 33091 if (hostSelectors) { 33092 const convertedSelectors = []; 33093 const hostSelectorArray = hostSelectors.split(',').map(p => p.trim()); 33094 33095 for (const hostSelector of hostSelectorArray) { 33096 if (!hostSelector) break; 33097 const convertedSelector = _polyfillHostNoCombinator + hostSelector.replace(_polyfillHost, '') + otherSelectors; 33098 convertedSelectors.push(convertedSelector); 33099 } 33100 33101 return convertedSelectors.join(','); 33102 } else { 33103 return _polyfillHostNoCombinator + otherSelectors; 33104 } 33105 }); 33106 } 33107 /* 33108 * convert a rule like :host-context(.foo) > .bar { } 33109 * 33110 * to 33111 * 33112 * .foo<scopeName> > .bar, .foo <scopeName> > .bar { } 33113 * 33114 * and 33115 * 33116 * :host-context(.foo:host) .bar { ... } 33117 * 33118 * to 33119 * 33120 * .foo<scopeName> .bar { ... } 33121 */ 33122 33123 33124 _convertColonHostContext(cssText) { 33125 return cssText.replace(_cssColonHostContextReGlobal, selectorText => { 33126 // We have captured a selector that contains a `:host-context` rule. 33127 // For backward compatibility `:host-context` may contain a comma separated list of selectors. 33128 // Each context selector group will contain a list of host-context selectors that must match 33129 // an ancestor of the host. 33130 // (Normally `contextSelectorGroups` will only contain a single array of context selectors.) 33131 const contextSelectorGroups = [[]]; // There may be more than `:host-context` in this selector so `selectorText` could look like: 33132 // `:host-context(.one):host-context(.two)`. 33133 // Execute `_cssColonHostContextRe` over and over until we have extracted all the 33134 // `:host-context` selectors from this selector. 33135 33136 let match; 33137 33138 while (match = _cssColonHostContextRe.exec(selectorText)) { 33139 // `match` = [':host-context(<selectors>)<rest>', <selectors>, <rest>] 33140 // The `<selectors>` could actually be a comma separated list: `:host-context(.one, .two)`. 33141 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. 33142 // For example if the current groups are: 33143 // ``` 33144 // [ 33145 // ['a', 'b', 'c'], 33146 // ['x', 'y', 'z'], 33147 // ] 33148 // ``` 33149 // And we have a new set of comma separated selectors: `:host-context(m,n)` then the new 33150 // groups are: 33151 // ``` 33152 // [ 33153 // ['a', 'b', 'c', 'm'], 33154 // ['x', 'y', 'z', 'm'], 33155 // ['a', 'b', 'c', 'n'], 33156 // ['x', 'y', 'z', 'n'], 33157 // ] 33158 // ``` 33159 33160 const contextSelectorGroupsLength = contextSelectorGroups.length; 33161 repeatGroups(contextSelectorGroups, newContextSelectors.length); 33162 33163 for (let i = 0; i < newContextSelectors.length; i++) { 33164 for (let j = 0; j < contextSelectorGroupsLength; j++) { 33165 contextSelectorGroups[j + i * contextSelectorGroupsLength].push(newContextSelectors[i]); 33166 } 33167 } // Update the `selectorText` and see repeat to see if there are more `:host-context`s. 33168 33169 33170 selectorText = match[2]; 33171 } // The context selectors now must be combined with each other to capture all the possible
33172 // selectors that `:host-context` can match. See `combineHostContextSelectors()` for more 33173 // info about how this is done. 33174 33175 33176 return contextSelectorGroups.map(contextSelectors => combineHostContextSelectors(contextSelectors, selectorText)).join(', '); 33177 }); 33178 } 33179 /* 33180 * Convert combinators like ::shadow and pseudo-elements like ::content 33181 * by replacing with space. 33182 */ 33183 33184 33185 _convertShadowDOMSelectors(cssText) { 33186 return _shadowDOMSelectorsRe.reduce((result, pattern) => result.replace(pattern, ' '), cssText); 33187 } // change a selector like 'div' to 'name div' 33188 33189 33190 _scopeSelectors(cssText, scopeSelector, hostSelector) { 33191 return processRules(cssText, rule => { 33192 let selector = rule.selector; 33193 let content = rule.content; 33194 33195 if (rule.selector[0] !== '@') { 33196 selector = this._scopeSelector(rule.selector, scopeSelector, hostSelector, this.strictStyling); 33197 } else if (rule.selector.startsWith('@media') || rule.selector.startsWith('@supports') || rule.selector.startsWith('@document') || rule.selector.startsWith('@layer')) { 33198 content = this._scopeSelectors(rule.content, scopeSelector, hostSelector); 33199 } else if (rule.selector.startsWith('@font-face') || rule.selector.startsWith('@page')) { 33200 content = this._stripScopingSelectors(rule.content); 33201 } 33202 33203 return new CssRule(selector, content); 33204 }); 33205 } 33206 /** 33207 * Handle a css text that is within a rule that should not contain scope selectors by simply 33208 * removing them! An example of such a rule is `@font-face`. 33209 * 33210 * `@font-face` rules cannot contain nested selectors. Nor can they be nested under a selector. 33211 * Normally this would be a syntax error by the author of the styles. But in some rare cases, such 33212 * as importing styles from a library, and applying `:host ::ng-deep` to the imported styles, we 33213 * can end up with broken css if the imported styles happen to contain @font-face rules. 33214 * 33215 * For example: 33216 * 33217 * ``` 33218 * :host ::ng-deep { 33219 * import 'some/lib/containing/font-face'; 33220 * } 33221 * 33222 * Similar logic applies to `@page` rules which can contain a particular set of properties, 33223 * as well as some specific at-rules. Since they can't be encapsulated, we have to strip 33224 * any scoping selectors from them. For more information: https://www.w3.org/TR/css-page-3 33225 * ``` 33226 */ 33227 33228 33229 _stripScopingSelectors(cssText) { 33230 return processRules(cssText, rule => { 33231 const selector = rule.selector.replace(_shadowDeepSelectors, ' ').replace(_polyfillHostNoCombinatorRe, ' '); 33232 return new CssRule(selector, rule.content); 33233 }); 33234 } 33235 33236 _scopeSelector(selector, scopeSelector, hostSelector, strict) { 33237 return selector.split(',').map(part => part.trim().split(_shadowDeepSelectors)).map(deepParts => { 33238 const [shallowPart, ...otherParts] = deepParts; 33239 33240 const applyScope = shallowPart => { 33241 if (this._selectorNeedsScoping(shallowPart, scopeSelector)) { 33242 return strict ? this._applyStrictSelectorScope(shallowPart, scopeSelector, hostSelector) : this._applySelectorScope(shallowPart, scopeSelector, hostSelector); 33243 } else { 33244 return shallowPart; 33245 } 33246 }; 33247 33248 return [applyScope(shallowPart), ...otherParts].join(' '); 33249 }).join(', '); 33250 } 33251 33252 _selectorNeedsScoping(selector, scopeSelector) { 33253 const re = this._makeScopeMatcher(scopeSelector); 33254 33255 return !re.test(selector); 33256 } 33257 33258 _makeScopeMatcher(scopeSelector) { 33259 const lre = /\[/g; 33260 const rre = /\]/g; 33261 scopeSelector = scopeSelector.replace(lre, '\\[').replace(rre, '\\]'); 33262 return new RegExp('^(' + scopeSelector + ')' + _selectorReSuffix, 'm'); 33263 } 33264 33265 _applySelectorScope(selector, scopeSelector, hostSelector) { 33266 // Difference from webcomponents.js: scopeSelector could not be an array 33267 return this._applySimpleSelectorScope(selector, scopeSelector, hostSelector); 33268 } // scope via name and [is=name] 33269 33270 33271 _applySimpleSelectorScope(selector, scopeSelector, hostSelector) { 33272 // In Android browser, the lastIndex is not reset when the regex is used in String.replace() 33273 _polyfillHostRe.lastIndex = 0; 33274 33275 if (_polyfillHostRe.test(selector)) { 33276 const replaceBy = this.strictStyling ? `[${hostSelector}]` : scopeSelector; 33277 return selector.replace(_polyfillHostNoCombinatorRe, (hnc, selector) => { 33278 return selector.replace(/([^:]*)(:*)(.*)/, (_, before, colon, after) => { 33279 return before + replaceBy + colon + after; 33280 }); 33281 }).replace(_polyfillHostRe, replaceBy + ' '); 33282 } 33283 33284 return scopeSelector + ' ' + selector; 33285 } // return a selector with [name] suffix on each simple selector 33286 // e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name] /** @internal */ 33287 33288 33289 _applyStrictSelectorScope(selector, scopeSelector, hostSelector) { 33290 const isRe = /\[is=([^\]]*)\]/g; 33291 scopeSelector = scopeSelector.replace(isRe, (_, ...parts) => parts[0]); 33292 const attrName = '[' + scopeSelector + ']'; 33293 33294 const _scopeSelectorPart = p => { 33295 let scopedP = p.trim(); 33296 33297 if (!scopedP) { 33298 return ''; 33299 } 33300 33301 if (p.indexOf(_polyfillHostNoCombinator) > -1) { 33302 scopedP = this._applySimpleSelectorScope(p, scopeSelector, hostSelector); 33303 } else { 33304 // remove :host since it should be unnecessary 33305 const t = p.replace(_polyfillHostRe, ''); 33306 33307 if (t.length > 0) { 33308 const matches = t.match(/([^:]*)(:*)(.*)/); 33309 33310 if (matches) { 33311 scopedP = matches[1] + attrName + matches[2] + matches[3]; 33312 } 33313 } 33314 } 33315 33316 return scopedP; 33317 }; 33318 33319 const safeContent = new SafeSelector(selector); 33320 selector = safeContent.content(); 33321 let scopedSelector = ''; 33322 let startIndex = 0; 33323 let res; 33324 const sep = /( |>|\+|~(?!=))\s*/g; // If a selector appears before :host it should not be shimmed as it 33325 // matches on ancestor elements and not on elements in the host's shadow 33326 // `:host-context(div)` is transformed to 33327 // `-shadowcsshost-no-combinatordiv, div -shadowcsshost-no-combinator` 33328 // the `div` is not part of the component in the 2nd selectors and should not be scoped. 33329 // Historically `component-tag:host` was matching the component so we also want to preserve 33330 // this behavior to avoid breaking legacy apps (it should not match). 33331 // The behavior should be: 33332 // - `tag:host` -> `tag[h]` (this is to avoid breaking legacy apps, should not match anything) 33333 // - `tag :host` -> `tag [h]` (`tag` is not scoped because it's considered part of a 33334 // `:host-context(tag)`) 33335 33336 const hasHost = selector.indexOf(_polyfillHostNoCombinator) > -1; // Only scope parts after the first `-shadowcsshost-no-combinator` when it is present 33337 33338 let shouldScope = !hasHost; 33339 33340 while ((res = sep.exec(selector)) !== null) { 33341 const separator = res[1]; 33342 const part = selector.slice(startIndex, res.index).trim(); 33343 shouldScope = shouldScope || part.indexOf(_polyfillHostNoCombinator) > -1; 33344 const scopedPart = shouldScope ? _scopeSelectorPart(part) : part;
33345 scopedSelector += `${scopedPart} ${separator} `; 33346 startIndex = sep.lastIndex; 33347 } 33348 33349 const part = selector.substring(startIndex); 33350 shouldScope = shouldScope || part.indexOf(_polyfillHostNoCombinator) > -1; 33351 scopedSelector += shouldScope ? _scopeSelectorPart(part) : part; // replace the placeholders with their original values 33352 33353 return safeContent.restore(scopedSelector); 33354 } 33355 33356 _insertPolyfillHostInCssText(selector) { 33357 return selector.replace(_colonHostContextRe, _polyfillHostContext).replace(_colonHostRe, _polyfillHost); 33358 } 33359 33360} 33361 33362class SafeSelector { 33363 constructor(selector) { 33364 this.placeholders = []; 33365 this.index = 0; // Replaces attribute selectors with placeholders. 33366 // The WS in [attr="va lue"] would otherwise be interpreted as a selector separator. 33367 33368 selector = this._escapeRegexMatches(selector, /(\[[^\]]*\])/g); // CSS allows for certain special characters to be used in selectors if they're escaped. 33369 // E.g. `.foo:blue` won't match a class called `foo:blue`, because the colon denotes a 33370 // pseudo-class, but writing `.foo\:blue` will match, because the colon was escaped. 33371 // Replace all escape sequences (`\` followed by a character) with a placeholder so 33372 // that our handling of pseudo-selectors doesn't mess with them. 33373 33374 selector = this._escapeRegexMatches(selector, /(\\.)/g); // Replaces the expression in `:nth-child(2n + 1)` with a placeholder. 33375 // WS and "+" would otherwise be interpreted as selector separators. 33376 33377 this._content = selector.replace(/(:nth-[-\w]+)(\([^)]+\))/g, (_, pseudo, exp) => { 33378 const replaceBy = `__ph-${this.index}__`; 33379 this.placeholders.push(exp); 33380 this.index++; 33381 return pseudo + replaceBy; 33382 }); 33383 } 33384 33385 restore(content) { 33386 return content.replace(/__ph-(\d+)__/g, (_ph, index) => this.placeholders[+index]); 33387 } 33388 33389 content() { 33390 return this._content; 33391 } 33392 /** 33393 * Replaces all of the substrings that match a regex within a 33394 * special string (e.g. `__ph-0__`, `__ph-1__`, etc). 33395 */ 33396 33397 33398 _escapeRegexMatches(content, pattern) { 33399 return content.replace(pattern, (_, keep) => { 33400 const replaceBy = `__ph-${this.index}__`; 33401 this.placeholders.push(keep); 33402 this.index++; 33403 return replaceBy; 33404 }); 33405 } 33406 33407} 33408 33409const _cssContentNextSelectorRe = /polyfill-next-selector[^}]*content:[\s]*?(['"])(.*?)\1[;\s]*}([^{]*?){/gim; 33410const _cssContentRuleRe = /(polyfill-rule)[^}]*(content:[\s]*(['"])(.*?)\3)[;\s]*[^}]*}/gim; 33411const _cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content:[\s]*(['"])(.*?)\3)[;\s]*[^}]*}/gim; 33412const _polyfillHost = '-shadowcsshost'; // note: :host-context pre-processed to -shadowcsshostcontext. 33413 33414const _polyfillHostContext = '-shadowcsscontext'; 33415 33416const _parenSuffix = '(?:\\((' + '(?:\\([^)(]*\\)|[^)(]*)+?' + ')\\))?([^,{]*)'; 33417 33418const _cssColonHostRe = new RegExp(_polyfillHost + _parenSuffix, 'gim'); 33419 33420const _cssColonHostContextReGlobal = new RegExp(_polyfillHostContext + _parenSuffix, 'gim'); 33421 33422const _cssColonHostContextRe = new RegExp(_polyfillHostContext + _parenSuffix, 'im'); 33423 33424const _polyfillHostNoCombinator = _polyfillHost + '-no-combinator'; 33425 33426const _polyfillHostNoCombinatorRe = /-shadowcsshost-no-combinator([^\s]*)/; 33427const _shadowDOMSelectorsRe = [/::shadow/g, /::content/g, // Deprecated selectors 33428/\/shadow-deep\//g, /\/shadow\//g]; // The deep combinator is deprecated in the CSS spec 33429// Support for `>>>`, `deep`, `::ng-deep` is then also deprecated and will be removed in the future. 33430// see https://github.com/angular/angular/pull/17677 33431 33432const _shadowDeepSelectors = /(?:>>>)|(?:\/deep\/)|(?:::ng-deep)/g; 33433const _selectorReSuffix = '([>\\s~+[.,{:][\\s\\S]*)?$'; 33434const _polyfillHostRe = /-shadowcsshost/gim; 33435const _colonHostRe = /:host/gim; 33436const _colonHostContextRe = /:host-context/gim; 33437const _commentRe = /\/\*[\s\S]*?\*\//g; 33438 33439function stripComments(input) { 33440 return input.replace(_commentRe, ''); 33441} 33442 33443const _commentWithHashRe = /\/\*\s*#\s*source(Mapping)?URL=[\s\S]+?\*\//g; 33444 33445function extractCommentsWithHash(input) { 33446 return input.match(_commentWithHashRe) || []; 33447} 33448 33449const BLOCK_PLACEHOLDER = '%BLOCK%'; 33450const QUOTE_PLACEHOLDER = '%QUOTED%'; 33451const _ruleRe = /(\s*)([^;\{\}]+?)(\s*)((?:{%BLOCK%}?\s*;?)|(?:\s*;))/g; 33452const _quotedRe = /%QUOTED%/g; 33453const CONTENT_PAIRS = new Map([['{', '}']]); 33454const QUOTE_PAIRS = new Map([[`"`, `"`], [`'`, `'`]]); 33455 33456class CssRule { 33457 constructor(selector, content) { 33458 this.selector = selector; 33459 this.content = content; 33460 } 33461 33462} 33463
33464function processRules(input, ruleCallback) { 33465 const inputWithEscapedQuotes = escapeBlocks(input, QUOTE_PAIRS, QUOTE_PLACEHOLDER); 33466 const inputWithEscapedBlocks = escapeBlocks(inputWithEscapedQuotes.escapedString, CONTENT_PAIRS, BLOCK_PLACEHOLDER); 33467 let nextBlockIndex = 0; 33468 let nextQuoteIndex = 0; 33469 return inputWithEscapedBlocks.escapedString.replace(_ruleRe, (...m) => { 33470 const selector = m[2]; 33471 let content = ''; 33472 let suffix = m[4]; 33473 let contentPrefix = ''; 33474 33475 if (suffix && suffix.startsWith('{' + BLOCK_PLACEHOLDER)) { 33476 content = inputWithEscapedBlocks.blocks[nextBlockIndex++]; 33477 suffix = suffix.substring(BLOCK_PLACEHOLDER.length + 1); 33478 contentPrefix = '{'; 33479 } 33480 33481 const rule = ruleCallback(new CssRule(selector, content)); 33482 return `${m[1]}${rule.selector}${m[3]}${contentPrefix}${rule.content}${suffix}`; 33483 }).replace(_quotedRe, () => inputWithEscapedQuotes.blocks[nextQuoteIndex++]); 33484} 33485 33486class StringWithEscapedBlocks { 33487 constructor(escapedString, blocks) { 33488 this.escapedString = escapedString; 33489 this.blocks = blocks; 33490 } 33491 33492} 33493 33494function escapeBlocks(input, charPairs, placeholder) { 33495 const resultParts = []; 33496 const escapedBlocks = []; 33497 let openCharCount = 0; 33498 let nonBlockStartIndex = 0; 33499 let blockStartIndex = -1; 33500 let openChar; 33501 let closeChar; 33502 33503 for (let i = 0; i < input.length; i++) { 33504 const char = input[i]; 33505 33506 if (char === '\\') { 33507 i++; 33508 } else if (char === closeChar) { 33509 openCharCount--; 33510 33511 if (openCharCount === 0) { 33512 escapedBlocks.push(input.substring(blockStartIndex, i)); 33513 resultParts.push(placeholder); 33514 nonBlockStartIndex = i; 33515 blockStartIndex = -1; 33516 openChar = closeChar = undefined; 33517 } 33518 } else if (char === openChar) { 33519 openCharCount++; 33520 } else if (openCharCount === 0 && charPairs.has(char)) { 33521 openChar = char; 33522 closeChar = charPairs.get(char); 33523 openCharCount = 1; 33524 blockStartIndex = i + 1; 33525 resultParts.push(input.substring(nonBlockStartIndex, blockStartIndex)); 33526 } 33527 } 33528 33529 if (blockStartIndex !== -1) { 33530 escapedBlocks.push(input.substring(blockStartIndex)); 33531 resultParts.push(placeholder); 33532 } else { 33533 resultParts.push(input.substring(nonBlockStartIndex)); 33534 } 33535 33536 return new StringWithEscapedBlocks(resultParts.join(''), escapedBlocks); 33537} 33538/** 33539 * Combine the `contextSelectors` with the `hostMarker` and the `otherSelectors` 33540 * to create a selector that matches the same as `:host-context()`. 33541 * 33542 * Given a single context selector `A` we need to output selectors that match on the host and as an 33543 * ancestor of the host: 33544 * 33545 * ``` 33546 * A <hostMarker>, A<hostMarker> {} 33547 * ``` 33548 * 33549 * When there is more than one context selector we also have to create combinations of those 33550 * selectors with each other. For example if there are `A` and `B` selectors the output is: 33551 * 33552 * ``` 33553 * AB<hostMarker>, AB <hostMarker>, A B<hostMarker>, 33554 * B A<hostMarker>, A B <hostMarker>, B A <hostMarker> {} 33555 * ``` 33556 * 33557 * And so on... 33558 * 33559 * @param hostMarker the string that selects the host element. 33560 * @param contextSelectors an array of context selectors that will be combined. 33561 * @param otherSelectors the rest of the selectors that are not context selectors. 33562 */ 33563 33564 33565function combineHostContextSelectors(contextSelectors, otherSelectors) { 33566 const hostMarker = _polyfillHostNoCombinator; 33567 _polyfillHostRe.lastIndex = 0; // reset the regex to ensure we get an accurate test 33568 33569 const otherSelectorsHasHost = _polyfillHostRe.test(otherSelectors); // If there are no context selectors then just output a host marker 33570 33571 33572 if (contextSelectors.length === 0) { 33573 return hostMarker + otherSelectors; 33574 } 33575 33576 const combined = [contextSelectors.pop() || '']; 33577 33578 while (contextSelectors.length > 0) { 33579 const length = combined.length; 33580 const contextSelector = contextSelectors.pop(); 33581 33582 for (let i = 0; i < length; i++) { 33583 const previousSelectors = combined[i]; // Add the new selector as a descendant of the previous selectors 33584 33585 combined[length * 2 + i] = previousSelectors + ' ' + contextSelector; // Add the new selector as an ancestor of the previous selectors 33586 33587 combined[length + i] = contextSelector + ' ' + previousSelectors; // Add the new selector to act on the same element as the previous selectors 33588 33589 combined[i] = contextSelector + previousSelectors; 33590 } 33591 } // Finally connect the selector to the `hostMarker`s: either acting directly on the host 33592 // (A<hostMarker>) or as an ancestor (A <hostMarker>). 33593 33594 33595 return combined.map(s => otherSelectorsHasHost ? `${s}${otherSelectors}` : `${s}${hostMarker}${otherSelectors}, ${s} ${hostMarker}${otherSelectors}`).join(','); 33596} 33597/** 33598 * Mutate the given `groups` array so that there are `multiples` clones of the original array 33599 * stored. 33600 * 33601 * For example `repeatGroups([a, b], 3)` will result in `[a, b, a, b, a, b]` - but importantly the 33602 * newly added groups will be clones of the original. 33603 *
33604 * @param groups An array of groups of strings that will be repeated. This array is mutated 33605 * in-place. 33606 * @param multiples The number of times the current groups should appear. 33607 */ 33608 33609 33610function repeatGroups(groups, multiples) { 33611 const length = groups.length; 33612 33613 for (let i = 1; i < multiples; i++) { 33614 for (let j = 0; j < length; j++) { 33615 groups[j + i * length] = groups[j].slice(0); 33616 } 33617 } 33618} 33619/** 33620 * @license 33621 * Copyright Google LLC All Rights Reserved. 33622 * 33623 * Use of this source code is governed by an MIT-style license that can be 33624 * found in the LICENSE file at https://angular.io/license 33625 */ 33626 33627/** 33628 * Parses string representation of a style and converts it into object literal. 33629 * 33630 * @param value string representation of style as used in the `style` attribute in HTML. 33631 * Example: `color: red; height: auto`. 33632 * @returns An array of style property name and value pairs, e.g. `['color', 'red', 'height', 33633 * 'auto']` 33634 */ 33635 33636 33637function parse(value) { 33638 // we use a string array here instead of a string map 33639 // because a string-map is not guaranteed to retain the 33640 // order of the entries whereas a string array can be 33641 // constructed in a [key, value, key, value] format. 33642 const styles = []; 33643 let i = 0; 33644 let parenDepth = 0; 33645 let quote = 0 33646 /* Char.QuoteNone */ 33647 ; 33648 let valueStart = 0; 33649 let propStart = 0; 33650 let currentProp = null; 33651 let valueHasQuotes = false; 33652 33653 while (i < value.length) { 33654 const token = value.charCodeAt(i++); 33655 33656 switch (token) { 33657 case 40 33658 /* Char.OpenParen */ 33659 : 33660 parenDepth++; 33661 break; 33662 33663 case 41 33664 /* Char.CloseParen */ 33665 : 33666 parenDepth--; 33667 break; 33668 33669 case 39 33670 /* Char.QuoteSingle */ 33671 : 33672 // valueStart needs to be there since prop values don't 33673 // have quotes in CSS 33674 valueHasQuotes = valueHasQuotes || valueStart > 0; 33675 33676 if (quote === 0 33677 /* Char.QuoteNone */ 33678 ) { 33679 quote = 39 33680 /* Char.QuoteSingle */ 33681 ; 33682 } else if (quote === 39 33683 /* Char.QuoteSingle */ 33684 && value.charCodeAt(i - 1) !== 92 33685 /* Char.BackSlash */ 33686 ) { 33687 quote = 0 33688 /* Char.QuoteNone */ 33689 ; 33690 } 33691 33692 break; 33693 33694 case 34 33695 /* Char.QuoteDouble */ 33696 : 33697 // same logic as above 33698 valueHasQuotes = valueHasQuotes || valueStart > 0; 33699 33700 if (quote === 0 33701 /* Char.QuoteNone */ 33702 ) { 33703 quote = 34 33704 /* Char.QuoteDouble */ 33705 ; 33706 } else if (quote === 34 33707 /* Char.QuoteDouble */ 33708 && value.charCodeAt(i - 1) !== 92 33709 /* Char.BackSlash */ 33710 ) { 33711 quote = 0 33712 /* Char.QuoteNone */ 33713 ; 33714 } 33715 33716 break; 33717 33718 case 58 33719 /* Char.Colon */ 33720 : 33721 if (!currentProp && parenDepth === 0 && quote === 0 33722 /* Char.QuoteNone */ 33723 ) { 33724 currentProp = hyphenate(value.substring(propStart, i - 1).trim()); 33725 valueStart = i; 33726 } 33727 33728 break; 33729 33730 case 59 33731 /* Char.Semicolon */ 33732 : 33733 if (currentProp && valueStart > 0 && parenDepth === 0 && quote === 0 33734 /* Char.QuoteNone */ 33735 ) { 33736 const styleVal = value.substring(valueStart, i - 1).trim(); 33737 styles.push(currentProp, valueHasQuotes ? stripUnnecessaryQuotes(styleVal) : styleVal); 33738 propStart = i; 33739 valueStart = 0; 33740 currentProp = null; 33741 valueHasQuotes = false; 33742 } 33743 33744 break; 33745 } 33746 } 33747 33748 if (currentProp && valueStart) { 33749 const styleVal = value.slice(valueStart).trim(); 33750 styles.push(currentProp, valueHasQuotes ? stripUnnecessaryQuotes(styleVal) : styleVal); 33751 } 33752 33753 return styles; 33754} 33755 33756function stripUnnecessaryQuotes(value) { 33757 const qS = value.charCodeAt(0); 33758 const qE = value.charCodeAt(value.length - 1); 33759 33760 if (qS == qE && (qS == 39 33761 /* Char.QuoteSingle */ 33762 || qS == 34 33763 /* Char.QuoteDouble */ 33764 )) { 33765 const tempValue = value.substring(1, value.length - 1); // special case to avoid using a multi-quoted string that was just chomped 33766 // (e.g. `font-family: "Verdana", "sans-serif"`) 33767 33768 if (tempValue.indexOf('\'') == -1 && tempValue.indexOf('"') == -1) { 33769 value = tempValue; 33770 } 33771 } 33772 33773 return value; 33774} 33775 33776function hyphenate(value) { 33777 return value.replace(/[a-z][A-Z]/g, v => { 33778 return v.charAt(0) + '-' + v.charAt(1); 33779 }).toLowerCase(); 33780} 33781 33782const IMPORTANT_FLAG = '!important'; 33783/** 33784 * Minimum amount of binding slots required in the runtime for style/class bindings. 33785 * 33786 * Styling in Angular uses up two slots in the runtime LView/TData data structures to 33787 * record binding data, property information and metadata. 33788 * 33789 * When a binding is registered it will place the following information in the `LView`: 33790 * 33791 * slot 1) binding value 33792 * slot 2) cached value (all other values collected before it in string form) 33793 * 33794 * When a binding is registered it will place the following information in the `TData`: 33795 * 33796 * slot 1) prop name 33797 * slot 2) binding index that points to the previous style/class binding (and some extra config 33798 * values) 33799 * 33800 * Let's imagine we have a binding that looks like so: 33801 * 33802 * ``` 33803 * <div [style.width]="x" [style.height]="y"> 33804 * ``` 33805 * 33806 * Our `LView` and `TData` data-structures look like so: 33807 * 33808 * ```typescript 33809 * LView = [ 33810 * // ... 33811 * x, // value of x 33812 * "width: x", 33813 * 33814 * y, // value of y 33815 * "width: x; height: y", 33816 * // ... 33817 * ]; 33818 * 33819 * TData = [ 33820 * // ... 33821 * "width", // binding slot 20 33822 * 0, 33823 *
33824 * "height", 33825 * 20, 33826 * // ... 33827 * ]; 33828 * ``` 33829 * 33830 * */ 33831 33832const MIN_STYLING_BINDING_SLOTS_REQUIRED = 2; 33833/** 33834 * Produces creation/update instructions for all styling bindings (class and style) 33835 * 33836 * It also produces the creation instruction to register all initial styling values 33837 * (which are all the static class="..." and style="..." attribute values that exist 33838 * on an element within a template). 33839 * 33840 * The builder class below handles producing instructions for the following cases: 33841 * 33842 * - Static style/class attributes (style="..." and class="...") 33843 * - Dynamic style/class map bindings ([style]="map" and [class]="map|string") 33844 * - Dynamic style/class property bindings ([style.prop]="exp" and [class.name]="exp") 33845 * 33846 * Due to the complex relationship of all of these cases, the instructions generated 33847 * for these attributes/properties/bindings must be done so in the correct order. The 33848 * order which these must be generated is as follows: 33849 * 33850 * if (createMode) { 33851 * styling(...) 33852 * } 33853 * if (updateMode) { 33854 * styleMap(...) 33855 * classMap(...) 33856 * styleProp(...) 33857 * classProp(...) 33858 * } 33859 * 33860 * The creation/update methods within the builder class produce these instructions. 33861 */ 33862 33863class StylingBuilder { 33864 constructor(_directiveExpr) { 33865 this._directiveExpr = _directiveExpr; 33866 /** Whether or not there are any static styling values present */ 33867 33868 this._hasInitialValues = false; 33869 /** 33870 * Whether or not there are any styling bindings present 33871 * (i.e. `[style]`, `[class]`, `[style.prop]` or `[class.name]`) 33872 */ 33873 33874 this.hasBindings = false; 33875 this.hasBindingsWithPipes = false; 33876 /** the input for [class] (if it exists) */ 33877 33878 this._classMapInput = null; 33879 /** the input for [style] (if it exists) */ 33880 33881 this._styleMapInput = null; 33882 /** an array of each [style.prop] input */ 33883 33884 this._singleStyleInputs = null; 33885 /** an array of each [class.name] input */ 33886 33887 this._singleClassInputs = null; 33888 this._lastStylingInput = null; 33889 this._firstStylingInput = null; // maps are used instead of hash maps because a Map will 33890 // retain the ordering of the keys 33891 33892 /** 33893 * Represents the location of each style binding in the template 33894 * (e.g. `<div [style.width]="w" [style.height]="h">` implies 33895 * that `width=0` and `height=1`) 33896 */ 33897 33898 this._stylesIndex = new Map(); 33899 /** 33900 * Represents the location of each class binding in the template 33901 * (e.g. `<div [class.big]="b" [class.hidden]="h">` implies 33902 * that `big=0` and `hidden=1`) 33903 */ 33904 33905 this._classesIndex = new Map(); 33906 this._initialStyleValues = []; 33907 this._initialClassValues = []; 33908 } 33909 /** 33910 * Registers a given input to the styling builder to be later used when producing AOT code. 33911 * 33912 * The code below will only accept the input if it is somehow tied to styling (whether it be 33913 * style/class bindings or static style/class attributes). 33914 */ 33915 33916 33917 registerBoundInput(input) { 33918 // [attr.style] or [attr.class] are skipped in the code below, 33919 // they should not be treated as styling-based bindings since 33920 // they are intended to be written directly to the attr and 33921 // will therefore skip all style/class resolution that is present 33922 // with style="", [style]="" and [style.prop]="", class="", 33923 // [class.prop]="". [class]="" assignments 33924 let binding = null; 33925 let name = input.name; 33926 33927 switch (input.type) { 33928 case 0 33929 /* BindingType.Property */ 33930 : 33931 binding = this.registerInputBasedOnName(name, input.value, input.sourceSpan); 33932 break; 33933 33934 case 3 33935 /* BindingType.Style */ 33936 : 33937 binding = this.registerStyleInput(name, false, input.value, input.sourceSpan, input.unit); 33938 break; 33939 33940 case 2 33941 /* BindingType.Class */ 33942 : 33943 binding = this.registerClassInput(name, false, input.value, input.sourceSpan); 33944 break; 33945 } 33946 33947 return binding ? true : false; 33948 } 33949 33950 registerInputBasedOnName(name, expression, sourceSpan) { 33951 let binding = null; 33952 const prefix = name.substring(0, 6); 33953 const isStyle = name === 'style' || prefix === 'style.' || prefix === 'style!'; 33954 const isClass = !isStyle && (name === 'class' || prefix === 'class.' || prefix === 'class!'); 33955 33956 if (isStyle || isClass) { 33957 const isMapBased = name.charAt(5) !== '.'; // style.prop or class.prop makes this a no 33958 33959 const property = name.slice(isMapBased ? 5 : 6); // the dot explains why there's a +1 33960 33961 if (isStyle) { 33962 binding = this.registerStyleInput(property, isMapBased, expression, sourceSpan); 33963 } else { 33964 binding = this.registerClassInput(property, isMapBased, expression, sourceSpan); 33965 } 33966 } 33967 33968 return binding; 33969 } 33970 33971 registerStyleInput(name, isMapBased, value, sourceSpan, suffix) { 33972 if (isEmptyExpression(value)) { 33973 return null; 33974 } // CSS custom properties are case-sensitive so we shouldn't normalize them. 33975 // See: https://www.w3.org/TR/css-variables-1/#defining-variables 33976 33977 33978 if (!isCssCustomProperty(name)) { 33979 name = hyphenate(name); 33980 } 33981 33982 const { 33983 property, 33984 hasOverrideFlag, 33985 suffix: bindingSuffix 33986 } = parseProperty(name); 33987 suffix = typeof suffix === 'string' && suffix.length !== 0 ? suffix : bindingSuffix; 33988 const entry = { 33989 name: property, 33990 suffix: suffix, 33991 value, 33992 sourceSpan, 33993 hasOverrideFlag 33994 }; 33995 33996 if (isMapBased) { 33997 this._styleMapInput = entry; 33998 } else { 33999 (this._singleStyleInputs = this._singleStyleInputs || []).push(entry); 34000 registerIntoMap(this._stylesIndex, property); 34001 } 34002 34003 this._lastStylingInput = entry; 34004 this._firstStylingInput = this._firstStylingInput || entry; 34005 34006 this._checkForPipes(value); 34007 34008 this.hasBindings = true; 34009 return entry; 34010 } 34011 34012 registerClassInput(name, isMapBased, value, sourceSpan) { 34013 if (isEmptyExpression(value)) { 34014 return null; 34015 } 34016 34017 const { 34018 property, 34019 hasOverrideFlag 34020 } = parseProperty(name); 34021 const entry = { 34022 name: property, 34023 value, 34024 sourceSpan, 34025 hasOverrideFlag, 34026 suffix: null 34027 }; 34028 34029 if (isMapBased) { 34030 this._classMapInput = entry; 34031 } else { 34032 (this._singleClassInputs = this._singleClassInputs || []).push(entry); 34033 registerIntoMap(this._classesIndex, property); 34034 } 34035 34036 this._lastStylingInput = entry; 34037 this._firstStylingInput = this._firstStylingInput || entry; 34038 34039 this._checkForPipes(value); 34040 34041 this.hasBindings = true; 34042 return entry; 34043 } 34044 34045 _checkForPipes(value) { 34046 if (value instanceof ASTWithSource && value.ast instanceof BindingPipe) { 34047 this.hasBindingsWithPipes = true; 34048 } 34049 } 34050 /** 34051 * Registers the element's static style string value to the builder. 34052 * 34053 * @param value the style string (e.g. `width:100px; height:200px;`) 34054 */ 34055 34056 34057 registerStyleAttr(value) { 34058 this._initialStyleValues = parse(value); 34059 this._hasInitialValues = true; 34060 } 34061 /** 34062 * Registers the element's static class string value to the builder. 34063 * 34064 * @param value the className string (e.g. `disabled gold zoom`) 34065 */ 34066 34067 34068 registerClassAttr(value) { 34069 this._initialClassValues = value.trim().split(/\s+/g); 34070 this._hasInitialValues = true; 34071 } 34072 /** 34073 * Appends all styling-related expressions to the provided attrs array. 34074 * 34075 * @param attrs an existing array where each of the styling expressions 34076 * will be inserted into. 34077 */ 34078 34079 34080 populateInitialStylingAttrs(attrs) { 34081 // [CLASS_MARKER, 'foo', 'bar', 'baz' ...] 34082 if (this._initialClassValues.length) { 34083 attrs.push(literal(1 34084 /* AttributeMarker.Classes */ 34085 )); 34086 34087 for (let i = 0; i < this._initialClassValues.length; i++) { 34088 attrs.push(literal(this._initialClassValues[i])); 34089 } 34090 } // [STYLE_MARKER, 'width', '200px', 'height', '100px', ...] 34091 34092 34093 if (this._initialStyleValues.length) { 34094 attrs.push(literal(2 34095 /* AttributeMarker.Styles */ 34096 )); 34097 34098 for (let i = 0; i < this._initialStyleValues.length; i += 2) { 34099 attrs.push(literal(this._initialStyleValues[i]), literal(this._initialStyleValues[i + 1])
34099); 34100 } 34101 } 34102 } 34103 /** 34104 * Builds an instruction with all the expressions and parameters for `elementHostAttrs`. 34105 * 34106 * The instruction generation code below is used for producing the AOT statement code which is 34107 * responsible for registering initial styles (within a directive hostBindings' creation block), 34108 * as well as any of the provided attribute values, to the directive host element. 34109 */ 34110 34111 34112 assignHostAttrs(attrs, definitionMap) { 34113 if (this._directiveExpr && (attrs.length || this._hasInitialValues)) { 34114 this.populateInitialStylingAttrs(attrs); 34115 definitionMap.set('hostAttrs', literalArr(attrs)); 34116 } 34117 } 34118 /** 34119 * Builds an instruction with all the expressions and parameters for `classMap`. 34120 * 34121 * The instruction data will contain all expressions for `classMap` to function 34122 * which includes the `[class]` expression params. 34123 */ 34124 34125 34126 buildClassMapInstruction(valueConverter) { 34127 if (this._classMapInput) { 34128 return this._buildMapBasedInstruction(valueConverter, true, this._classMapInput); 34129 } 34130 34131 return null; 34132 } 34133 /** 34134 * Builds an instruction with all the expressions and parameters for `styleMap`. 34135 * 34136 * The instruction data will contain all expressions for `styleMap` to function 34137 * which includes the `[style]` expression params. 34138 */ 34139 34140 34141 buildStyleMapInstruction(valueConverter) { 34142 if (this._styleMapInput) { 34143 return this._buildMapBasedInstruction(valueConverter, false, this._styleMapInput); 34144 } 34145 34146 return null; 34147 } 34148 34149 _buildMapBasedInstruction(valueConverter, isClassBased, stylingInput) { 34150 // each styling binding value is stored in the LView 34151 // map-based bindings allocate two slots: one for the 34152 // previous binding value and another for the previous 34153 // className or style attribute value. 34154 let totalBindingSlotsRequired = MIN_STYLING_BINDING_SLOTS_REQUIRED; // these values must be outside of the update block so that they can 34155 // be evaluated (the AST visit call) during creation time so that any 34156 // pipes can be picked up in time before the template is built 34157 34158 const mapValue = stylingInput.value.visit(valueConverter); 34159 let reference; 34160 34161 if (mapValue instanceof Interpolation) { 34162 totalBindingSlotsRequired += mapValue.expressions.length; 34163 reference = isClassBased ? getClassMapInterpolationExpression(mapValue) : getStyleMapInterpolationExpression(mapValue); 34164 } else { 34165 reference = isClassBased ? Identifiers.classMap : Identifiers.styleMap; 34166 } 34167 34168 return { 34169 reference, 34170 calls: [{ 34171 supportsInterpolation: true, 34172 sourceSpan: stylingInput.sourceSpan, 34173 allocateBindingSlots: totalBindingSlotsRequired, 34174 params: convertFn => { 34175 const convertResult = convertFn(mapValue); 34176 const params = Array.isArray(convertResult) ? convertResult : [convertResult]; 34177 return params; 34178 } 34179 }] 34180 }; 34181 } 34182 34183 _buildSingleInputs(reference, inputs, valueConverter, getInterpolationExpressionFn, isClassBased) { 34184 const instructions = []; 34185 inputs.forEach(input => { 34186 const previousInstruction = instructions[instructions.length - 1]; 34187 const value = input.value.visit(valueConverter); 34188 let referenceForCall = reference; // each styling binding value is stored in the LView 34189 // but there are two values stored for each binding: 34190 // 1) the value itself 34191 // 2) an intermediate value (concatenation of style up to this point). 34192 // We need to store the intermediate value so that we don't allocate 34193 // the strings on each CD. 34194 34195 let totalBindingSlotsRequired = MIN_STYLING_BINDING_SLOTS_REQUIRED; 34196 34197 if (value instanceof Interpolation) { 34198 totalBindingSlotsRequired += value.expressions.length; 34199 34200 if (getInterpolationExpressionFn) { 34201 referenceForCall = getInterpolationExpressionFn(value); 34202 } 34203 } 34204 34205 const call = { 34206 sourceSpan: input.sourceSpan, 34207 allocateBindingSlots: totalBindingSlotsRequired, 34208 supportsInterpolation: !!getInterpolationExpressionFn, 34209 params: convertFn => { 34210 // params =>
34210 stylingProp(propName, value, suffix) 34211 const params = []; 34212 params.push(literal(input.name)); 34213 const convertResult = convertFn(value); 34214 34215 if (Array.isArray(convertResult)) { 34216 params.push(...convertResult); 34217 } else { 34218 params.push(convertResult); 34219 } // [style.prop] bindings may use suffix values (e.g. px, em, etc...), therefore, 34220 // if that is detected then we need to pass that in as an optional param. 34221 34222 34223 if (!isClassBased && input.suffix !== null) { 34224 params.push(literal(input.suffix)); 34225 } 34226 34227 return params; 34228 } 34229 }; // If we ended up generating a call to the same instruction as the previous styling property 34230 // we can chain the calls together safely to save some bytes, otherwise we have to generate 34231 // a separate instruction call. This is primarily a concern with interpolation instructions 34232 // where we may start off with one `reference`, but end up using another based on the 34233 // number of interpolations. 34234 34235 if (previousInstruction && previousInstruction.reference === referenceForCall) { 34236 previousInstruction.calls.push(call); 34237 } else { 34238 instructions.push({ 34239 reference: referenceForCall, 34240 calls: [call] 34241 }); 34242 } 34243 }); 34244 return instructions; 34245 } 34246 34247 _buildClassInputs(valueConverter) { 34248 if (this._singleClassInputs) { 34249 return this._buildSingleInputs(Identifiers.classProp, this._singleClassInputs, valueConverter, null, true); 34250 } 34251 34252 return []; 34253 } 34254 34255 _buildStyleInputs(valueConverter) { 34256 if (this._singleStyleInputs) { 34257 return this._buildSingleInputs(Identifiers.styleProp, this._singleStyleInputs, valueConverter, getStylePropInterpolationExpression, false); 34258 } 34259 34260 return []; 34261 } 34262 /** 34263 * Constructs all instructions which contain the expressions that will be placed 34264 * into the update block of a template function or a directive hostBindings function. 34265 */ 34266 34267 34268 buildUpdateLevelInstructions(valueConverter) { 34269 const instructions = []; 34270 34271 if (this.hasBindings) { 34272 const styleMapInstruction = this.buildStyleMapInstruction(valueConverter); 34273 34274 if (styleMapInstruction) { 34275 instructions.push(styleMapInstruction); 34276 } 34277 34278 const classMapInstruction = this.buildClassMapInstruction(valueConverter); 34279 34280 if (classMapInstruction) { 34281 instructions.push(classMapInstruction); 34282 } 34283 34284 instructions.push(...this._buildStyleInputs(valueConverter)); 34285 instructions.push(...this._buildClassInputs(valueConverter)); 34286 } 34287 34288 return instructions; 34289 } 34290 34291} 34292 34293function registerIntoMap(map, key) { 34294 if (!map.has(key)) { 34295 map.set(key, map.size); 34296 } 34297} 34298 34299function parseProperty(name) { 34300 let hasOverrideFlag = false; 34301 const overrideIndex = name.indexOf(IMPORTANT_FLAG); 34302 34303 if (overrideIndex !== -1) { 34304 name = overrideIndex > 0 ? name.substring(0, overrideIndex) : ''; 34305 hasOverrideFlag = true; 34306 } 34307 34308 let suffix = null; 34309 let property = name; 34310 const unitIndex = name.lastIndexOf('.'); 34311 34312 if (unitIndex > 0) { 34313 suffix = name.slice(unitIndex + 1); 34314 property = name.substring(0, unitIndex); 34315 } 34316 34317 return { 34318 property, 34319 suffix, 34320 hasOverrideFlag 34321 }; 34322} 34323/** 34324 * Gets the instruction to generate for an interpolated class map. 34325 * @param interpolation An Interpolation AST 34326 */ 34327 34328 34329function getClassMapInterpolationExpression(interpolation) { 34330 switch (getInterpolationArgsLength(interpolation)) { 34331 case 1: 34332 return Identifiers.classMap; 34333 34334 case 3: 34335 return Identifiers.classMapInterpolate1; 34336 34337 case 5: 34338 return Identifiers.classMapInterpolate2; 34339 34340 case 7: 34341 return Identifiers.classMapInterpolate3; 34342 34343 case 9: 34344 return Identifiers.classMapInterpolate4; 34345 34346 case 11: 34347 return Identifiers.classMapInterpolate5; 34348 34349 case 13: 34350 return Identifiers.classMapInterpolate6; 34351 34352 case 15: 34353 return Identifiers.classMapInterpolate7; 34354 34355 case 17: 34356 return Identifiers.classMapInterpolate8; 34357 34358 default: 34359 return Identifiers.classMapInterpolateV; 34360 } 34361} 34362/** 34363 * Gets the instruction to generate for an interpolated style map. 34364 * @param interpolation An Interpolation AST 34365 */ 34366 34367 34368function getStyleMapInterpolationExpression(interpolation) { 34369 switch (getInterpolationArgsLength(interpolation)) { 34370 case 1: 34371 return Identifiers.styleMap; 34372 34373 case 3: 34374 return Identifiers.styleMapInterpolate1; 34375 34376 case 5: 34377 return Identifiers.styleMapInterpolate2; 34378 34379 case 7: 34380 return Identifiers.styleMapInterpolate3; 34381 34382 case 9: 34383 return Identifiers.styleMapInterpolate4; 34384 34385 case 11: 34386 return Identifiers.styleMapInterpolate5; 34387 34388 case 13: 34389 return Identifiers.styleMapInterpolate6; 34390 34391 case 15: 34392 return Identifiers.styleMapInterpolate7; 34393 34394 case 17: 34395 return Identifiers.styleMapInterpolate8; 34396 34397 default: 34398 return Identifiers.styleMapInterpolateV; 34399 } 34400} 34401/** 34402 * Gets the instruction to generate for an interpolated style prop. 34403 * @param interpolation An Interpolation AST 34404 */ 34405 34406 34407function getStylePropInterpolationExpression(interpolation) { 34408 switch (getInterpolationArgsLength(interpolation)) { 34409 case 1: 34410 return Identifiers.styleProp; 34411 34412 case 3: 34413 return Identifiers.stylePropInterpolate1; 34414 34415 case 5: 34416 return Identifiers.stylePropInterpolate2; 34417 34418 case 7: 34419 return Identifiers.stylePropInterpolate3; 34420 34421 case 9: 34422 return Identifiers.stylePropInterpolate4; 34423 34424 case 11: 34425 return Identifiers.stylePropInterpolate5; 34426 34427 case 13: 34428 return Identifiers.stylePropInterpolate6; 34429 34430 case 15: 34431 return Identifiers.stylePropInterpolate7; 34432 34433 case 17: 34434 return Identifiers.stylePropInterpolate8; 34435 34436 default: 34437 return Identifiers.stylePropInterpolateV; 34438 } 34439} 34440/** 34441 * Checks whether property name is a custom CSS property. 34442 * See: https://www.w3.org/TR/css-variables-1 34443 */ 34444 34445 34446function isCssCustomProperty(name) { 34447 return name.startsWith('--'); 34448} 34449 34450function isEmptyExpression(ast) { 34451 if (ast instanceof ASTWithSource) { 34452 ast = ast.ast; 34453 } 34454 34455 return ast instanceof EmptyExpr; 34456} 34457/** 34458 * @license 34459 * Copyright Google LLC All Rights Reserved. 34460 * 34461 * Use of this source code is governed by an MIT-style license that can be 34462 * found in the LICENSE file at https://angular.io/license 34463 */ 34464 34465 34466var TokenType; 34467 34468(function (TokenType) { 34469 TokenType[TokenType["Character"] = 0] = "Character"; 34470 TokenType[TokenType["Identifier"] = 1] = "Identifier"; 34471 TokenType[TokenType["PrivateIdentifier"] = 2] = "PrivateIdentifier"; 34472 TokenType[TokenType["Keyword"] = 3] = "Keyword"; 34473 TokenType[TokenType["String"] = 4] = "String"; 34474 TokenType[TokenType["Operator"] = 5] = "Operator"; 34475 TokenType[TokenType["Number"] = 6] = "Number"; 34476 TokenType[TokenType["Error"] = 7] = "Error"; 34477})(TokenType || (TokenType = {})); 34478 34479const KEYWORDS = ['var', 'let', 'as', 'null', 'undefined', 'true', 'false', 'if', 'else', 'this']; 34480 34481class Lexer { 34482 tokenize(text) { 34483 const scanner = new _Scanner(text); 34484 const tokens = []; 34485 let token = scanner.scanToken(); 34486 34487 while (token != null) { 34488 tokens.push(token); 34489 token = scanner.scanToken(); 34490 } 34491 34492 return tokens; 34493 } 34494 34495} 34496 34497class Token { 34498 constructor(index, end, type, numValue, strValue) { 34499 this.index = index; 34500 this.end = end; 34501 this.type = type; 34502 this.numValue = numValue; 34503 this.strValue = strValue; 34504 } 34505 34506 isCharacter(code) { 34507 return this.type == TokenType.Character && this.numValue == code; 34508 } 34509 34510 isNumber() { 34511 return this.type == TokenType.Number; 34512 } 34513 34514 isString() { 34515 return this.type == TokenType.String; 34516 } 34517 34518 isOperator(operator) { 34519 return this.type == TokenType.Operator && this.strValue == operator; 34520 } 34521 34522 isIdentifier() { 34523 return this.type == TokenType.Identifier; 34524 } 34525 34526 isPrivateIdentifier() { 34527 return this.type == TokenType.PrivateIdentifier; 34528 } 34529 34530 isKeyword() { 34531 return this.type == TokenType.Keyword; 34532 } 34533 34534 isKeywordLet() { 34535 return this.type == TokenType.Keyword && this.strValue == 'let'; 34536 } 34537 34538 isKeywordAs() { 34539 return this.type == TokenType.Keyword && this.strValue == 'as'; 34540 } 34541 34542 isKeywordNull() { 34543 return this.type == TokenType.Keyword && this.strValue == 'null';
34544 } 34545 34546 isKeywordUndefined() { 34547 return this.type == TokenType.Keyword && this.strValue == 'undefined'; 34548 } 34549 34550 isKeywordTrue() { 34551 return this.type == TokenType.Keyword && this.strValue == 'true'; 34552 } 34553 34554 isKeywordFalse() { 34555 return this.type == TokenType.Keyword && this.strValue == 'false'; 34556 } 34557 34558 isKeywordThis() { 34559 return this.type == TokenType.Keyword && this.strValue == 'this'; 34560 } 34561 34562 isError() { 34563 return this.type == TokenType.Error; 34564 } 34565 34566 toNumber() { 34567 return this.type == TokenType.Number ? this.numValue : -1; 34568 } 34569 34570 toString() { 34571 switch (this.type) { 34572 case TokenType.Character: 34573 case TokenType.Identifier: 34574 case TokenType.Keyword: 34575 case TokenType.Operator: 34576 case TokenType.PrivateIdentifier: 34577 case TokenType.String: 34578 case TokenType.Error: 34579 return this.strValue; 34580 34581 case TokenType.Number: 34582 return this.numValue.toString(); 34583 34584 default: 34585 return null; 34586 } 34587 } 34588 34589} 34590 34591function newCharacterToken(index, end, code) { 34592 return new Token(index, end, TokenType.Character, code, String.fromCharCode(code)); 34593} 34594 34595function newIdentifierToken(index, end, text) { 34596 return new Token(index, end, TokenType.Identifier, 0, text); 34597} 34598 34599function newPrivateIdentifierToken(index, end, text) { 34600 return new Token(index, end, TokenType.PrivateIdentifier, 0, text); 34601} 34602 34603function newKeywordToken(index, end, text) { 34604 return new Token(index, end, TokenType.Keyword, 0, text); 34605} 34606 34607function newOperatorToken(index, end, text) { 34608 return new Token(index, end, TokenType.Operator, 0, text); 34609} 34610 34611function newStringToken(index, end, text) { 34612 return new Token(index, end, TokenType.String, 0, text); 34613} 34614 34615function newNumberToken(index, end, n) { 34616 return new Token(index, end, TokenType.Number, n, ''); 34617} 34618 34619function newErrorToken(index, end, message) { 34620 return new Token(index, end, TokenType.Error, 0, message); 34621} 34622 34623const EOF = new Token(-1, -1, TokenType.Character, 0, ''); 34624 34625class _Scanner { 34626 constructor(input) { 34627 this.input = input; 34628 this.peek = 0; 34629 this.index = -1; 34630 this.length = input.length; 34631 this.advance(); 34632 } 34633 34634 advance() { 34635 this.peek = ++this.index >= this.length ? $EOF : this.input.charCodeAt(this.index); 34636 } 34637 34638 scanToken() { 34639 const input = this.input, 34640 length = this.length; 34641 let peek = this.peek, 34642 index = this.index; // Skip whitespace. 34643 34644 while (peek <= $SPACE) { 34645 if (++index >= length) { 34646 peek = $EOF; 34647 break; 34648 } else { 34649 peek = input.charCodeAt(index); 34650 } 34651 } 34652 34653 this.peek = peek; 34654 this.index = index; 34655 34656 if (index >= length) { 34657 return null; 34658 } // Handle identifiers and numbers. 34659 34660 34661 if (isIdentifierStart(peek)) return this.scanIdentifier(); 34662 if (isDigit(peek)) return this.scanNumber(index); 34663 const start = index; 34664 34665 switch (peek) { 34666 case $PERIOD: 34667 this.advance(); 34668 return isDigit(this.peek) ? this.scanNumber(start) : newCharacterToken(start, this.index, $PERIOD); 34669 34670 case $LPAREN: 34671 case $RPAREN: 34672 case $LBRACE: 34673 case $RBRACE: 34674 case $LBRACKET: 34675 case $RBRACKET: 34676 case $COMMA: 34677 case $COLON: 34678 case $SEMICOLON: 34679 return this.scanCharacter(start, peek); 34680 34681 case $SQ: 34682 case $DQ: 34683 return this.scanString(); 34684 34685 case $HASH: 34686 return this.scanPrivateIdentifier(); 34687 34688 case $PLUS: 34689 case $MINUS: 34690 case $STAR: 34691 case $SLASH: 34692 case $PERCENT: 34693 case $CARET: 34694 return this.scanOperator(start, String.fromCharCode(peek)); 34695 34696 case $QUESTION: 34697 return this.scanQuestion(start); 34698 34699 case $LT: 34700 case $GT: 34701 return this.scanComplexOperator(start, String.fromCharCode(peek), $EQ, '='); 34702 34703 case $BANG: 34704 case $EQ: 34705 return this.scanComplexOperator(start, String.fromCharCode(peek), $EQ, '=', $EQ, '='); 34706 34707 case $AMPERSAND: 34708 return this.scanComplexOperator(start, '&', $AMPERSAND, '&'); 34709 34710 case $BAR: 34711 return this.scanComplexOperator(start, '|', $BAR, '|'); 34712 34713 case $NBSP: 34714 while (isWhitespace(this.peek)) this.advance(); 34715 34716 return this.scanToken(); 34717 } 34718 34719 this.advance(); 34720 return this.error(`Unexpected character [${String.fromCharCode(peek)}]`, 0); 34721 } 34722
34723 scanCharacter(start, code) { 34724 this.advance(); 34725 return newCharacterToken(start, this.index, code); 34726 } 34727 34728 scanOperator(start, str) { 34729 this.advance(); 34730 return newOperatorToken(start, this.index, str); 34731 } 34732 /** 34733 * Tokenize a 2/3 char long operator 34734 * 34735 * @param start start index in the expression 34736 * @param one first symbol (always part of the operator) 34737 * @param twoCode code point for the second symbol 34738 * @param two second symbol (part of the operator when the second code point matches) 34739 * @param threeCode code point for the third symbol 34740 * @param three third symbol (part of the operator when provided and matches source expression) 34741 */ 34742 34743 34744 scanComplexOperator(start, one, twoCode, two, threeCode, three) { 34745 this.advance(); 34746 let str = one; 34747 34748 if (this.peek == twoCode) { 34749 this.advance(); 34750 str += two; 34751 } 34752 34753 if (threeCode != null && this.peek == threeCode) { 34754 this.advance(); 34755 str += three; 34756 } 34757 34758 return newOperatorToken(start, this.index, str); 34759 } 34760 34761 scanIdentifier() { 34762 const start = this.index; 34763 this.advance(); 34764 34765 while (isIdentifierPart(this.peek)) this.advance(); 34766 34767 const str = this.input.substring(start, this.index); 34768 return KEYWORDS.indexOf(str) > -1 ? newKeywordToken(start, this.index, str) : newIdentifierToken(start, this.index, str); 34769 } 34770 /** Scans an ECMAScript private identifier. */ 34771 34772 34773 scanPrivateIdentifier() { 34774 const start = this.index; 34775 this.advance(); 34776 34777 if (!isIdentifierStart(this.peek)) { 34778 return this.error('Invalid character [#]', -1); 34779 } 34780 34781 while (isIdentifierPart(this.peek)) this.advance(); 34782 34783 const identifierName = this.input.substring(start, this.index); 34784 return newPrivateIdentifierToken(start, this.index, identifierName); 34785 } 34786 34787 scanNumber(start) { 34788 let simple = this.index === start; 34789 let hasSeparators = false; 34790 this.advance(); // Skip initial digit. 34791 34792 while (true) { 34793 if (isDigit(this.peek)) {// Do nothing. 34794 } else if (this.peek === $_) { 34795 // Separators are only valid when they're surrounded by digits. E.g. `1_0_1` is 34796 // valid while `_101` and `101_` are not. The separator can't be next to the decimal 34797 // point or another separator either. Note that it's unlikely that we'll hit a case where 34798 // the underscore is at the start, because that's a valid identifier and it will be picked 34799 // up earlier in the parsing. We validate for it anyway just in case. 34800 if (!isDigit(this.input.charCodeAt(this.index - 1)) || !isDigit(this.input.charCodeAt(this.index + 1))) { 34801 return this.error('Invalid numeric separator', 0); 34802 } 34803 34804 hasSeparators = true; 34805 } else if (this.peek === $PERIOD) { 34806 simple = false; 34807 } else if (isExponentStart(this.peek)) { 34808 this.advance(); 34809 if (isExponentSign(this.peek)) this.advance(); 34810 if (!isDigit(this.peek)) return this.error('Invalid exponent', -1); 34811 simple = false; 34812 } else { 34813 break; 34814 } 34815 34816 this.advance(); 34817 } 34818 34819 let str = this.input.substring(start, this.index); 34820 34821 if (hasSeparators) { 34822 str = str.replace(/_/g, ''); 34823 } 34824 34825 const value = simple ? parseIntAutoRadix(str) : parseFloat(str); 34826 return newNumberToken(start, this.index, value); 34827 } 34828 34829 scanString() { 34830 const start = this.index; 34831 const quote = this.peek; 34832 this.advance(); // Skip initial quote. 34833 34834 let buffer = ''; 34835 let marker = this.index; 34836 const input = this.input; 34837 34838 while (this.peek != quote) { 34839 if (this.peek == $BACKSLASH) { 34840 buffer += input.substring(marker, this.index); 34841 this.advance(); 34842 let unescapedCode; // Workaround for TS2.1-introduced type strictness 34843 34844 this.peek = this.peek; 34845 34846 if (this.peek == $u) { 34847 // 4 character hex code for unicode character. 34848 const hex = input.substring(this.index + 1, this.index + 5); 34849 34850 if (/^[0-9a-f]+$/i.test(hex)) { 34851 unescapedCode = parseInt(hex, 16); 34852 } else { 34853 return this.error(`Invalid unicode escape [\\u${hex}]`, 0); 34854 } 34855 34856 for (let i = 0; i < 5; i++) { 34857 this.advance(); 34858 } 34859 } else { 34860 unescapedCode = unescape(this.peek); 34861 this.advance(); 34862 } 34863 34864 buffer += String.fromCharCode(unescapedCode); 34865 marker = this.index; 34866 } else if (this.peek == $EOF) {
34867 return this.error('Unterminated quote', 0); 34868 } else { 34869 this.advance(); 34870 } 34871 } 34872 34873 const last = input.substring(marker, this.index); 34874 this.advance(); // Skip terminating quote. 34875 34876 return newStringToken(start, this.index, buffer + last); 34877 } 34878 34879 scanQuestion(start) { 34880 this.advance(); 34881 let str = '?'; // Either `a ?? b` or 'a?.b'. 34882 34883 if (this.peek === $QUESTION || this.peek === $PERIOD) { 34884 str += this.peek === $PERIOD ? '.' : '?'; 34885 this.advance(); 34886 } 34887 34888 return newOperatorToken(start, this.index, str); 34889 } 34890 34891 error(message, offset) { 34892 const position = this.index + offset; 34893 return newErrorToken(position, this.index, `Lexer Error: ${message} at column ${position} in expression [${this.input}]`); 34894 } 34895 34896} 34897 34898function isIdentifierStart(code) { 34899 return $a <= code && code <= $z || $A <= code && code <= $Z || code == $_ || code == $$; 34900} 34901 34902function isIdentifier(input) { 34903 if (input.length == 0) return false; 34904 const scanner = new _Scanner(input); 34905 if (!isIdentifierStart(scanner.peek)) return false; 34906 scanner.advance(); 34907 34908 while (scanner.peek !== $EOF) { 34909 if (!isIdentifierPart(scanner.peek)) return false; 34910 scanner.advance(); 34911 } 34912 34913 return true; 34914} 34915 34916function isIdentifierPart(code) { 34917 return isAsciiLetter(code) || isDigit(code) || code == $_ || code == $$; 34918} 34919 34920function isExponentStart(code) { 34921 return code == $e || code == $E; 34922} 34923 34924function isExponentSign(code) { 34925 return code == $MINUS || code == $PLUS; 34926} 34927 34928function unescape(code) { 34929 switch (code) { 34930 case $n: 34931 return $LF; 34932 34933 case $f: 34934 return $FF; 34935 34936 case $r: 34937 return $CR; 34938 34939 case $t: 34940 return $TAB; 34941 34942 case $v: 34943 return $VTAB; 34944 34945 default: 34946 return code; 34947 } 34948} 34949 34950function parseIntAutoRadix(text) { 34951 const result = parseInt(text); 34952 34953 if (isNaN(result)) { 34954 throw new Error('Invalid integer literal when parsing ' + text); 34955 } 34956 34957 return result; 34958} 34959/** 34960 * @license 34961 * Copyright Google LLC All Rights Reserved. 34962 * 34963 * Use of this source code is governed by an MIT-style license that can be 34964 * found in the LICENSE file at https://angular.io/license 34965 */ 34966 34967 34968class SplitInterpolation { 34969 constructor(strings, expressions, offsets) { 34970 this.strings = strings; 34971 this.expressions = expressions; 34972 this.offsets = offsets; 34973 } 34974 34975} 34976 34977class TemplateBindingParseResult { 34978 constructor(templateBindings, warnings, errors) { 34979 this.templateBindings = templateBindings; 34980 this.warnings = warnings; 34981 this.errors = errors; 34982 } 34983 34984} 34985 34986class Parser$1 { 34987 constructor(_lexer) { 34988 this._lexer = _lexer; 34989 this.errors = []; 34990 } 34991 34992 parseAction(input, isAssignmentEvent, location, absoluteOffset, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) { 34993 this._checkNoInterpolation(input, location, interpolationConfig); 34994 34995 const sourceToLex = this._stripComments(input); 34996 34997 const tokens = this._lexer.tokenize(sourceToLex); 34998 34999 let flags = 1 35000 /* ParseFlags.Action */ 35001 ; 35002 35003 if (isAssignmentEvent) { 35004 flags |= 2 35005 /* ParseFlags.AssignmentEvent */ 35006 ; 35007 } 35008 35009 const ast = new _ParseAST(input, location, absoluteOffset, tokens, flags, this.errors, 0).parseChain(); 35010 return new ASTWithSource(ast, input, location, absoluteOffset, this.errors); 35011 } 35012 35013 parseBinding(input, location, absoluteOffset, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) { 35014 const ast = this._parseBindingAst(input, location, absoluteOffset, interpolationConfig); 35015 35016 return new ASTWithSource(ast, input, location, absoluteOffset, this.errors); 35017 } 35018 35019 checkSimpleExpression(ast) { 35020 const checker = new SimpleExpressionChecker(); 35021 ast.visit(checker); 35022 return checker.errors; 35023 } 35024 35025 parseSimpleBinding(input, location, absoluteOffset, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) { 35026 const ast = this._parseBindingAst(input, location, absoluteOffset, interpolationConfig); 35027 35028 const errors = this.checkSimpleExpression(ast); 35029 35030 if (errors.length > 0) { 35031 this._reportError(`Host binding expression cannot contain ${errors.join(' ')}`, input, location); 35032 } 35033 35034 return new ASTWithSource(ast, input, location, absoluteOffset, this.errors); 35035 } 35036 35037 _reportError(message, input, errLocation, ctxLocation) { 35038 this.errors.push(new ParserError(message, input, errLocation, ctxLocation)); 35039 } 35040 35041 _parseBindingAst(input, location, absoluteOffset, interpolationConfig) { 35042 this._checkNoInterpolation(input, location, interpolationConfig); 35043 35044 const sourceToLex = this._stripComments(input); 35045 35046 const tokens = this._lexer.tokenize(sourceToLex); 35047 35048 return new _ParseAST(input, location, absoluteOffset, tokens, 0 35049 /* ParseFlags.None */ 35050 , this.errors, 0).parseChain(); 35051 } 35052 /** 35053 * Parse microsyntax template expression and return a list of bindings or
35054 * parsing errors in case the given expression is invalid. 35055 * 35056 * For example, 35057 * ``` 35058 * <div *ngFor="let item of items"> 35059 * ^ ^ absoluteValueOffset for `templateValue` 35060 * absoluteKeyOffset for `templateKey` 35061 * ``` 35062 * contains three bindings: 35063 * 1. ngFor -> null 35064 * 2. item -> NgForOfContext.$implicit 35065 * 3. ngForOf -> items 35066 * 35067 * This is apparent from the de-sugared template: 35068 * ``` 35069 * <ng-template ngFor let-item [ngForOf]="items"> 35070 * ``` 35071 * 35072 * @param templateKey name of directive, without the * prefix. For example: ngIf, ngFor 35073 * @param templateValue RHS of the microsyntax attribute 35074 * @param templateUrl template filename if it's external, component filename if it's inline 35075 * @param absoluteKeyOffset start of the `templateKey` 35076 * @param absoluteValueOffset start of the `templateValue` 35077 */ 35078 35079 35080 parseTemplateBindings(templateKey, templateValue, templateUrl, absoluteKeyOffset, absoluteValueOffset) { 35081 const tokens = this._lexer.tokenize(templateValue); 35082 35083 const parser = new _ParseAST(templateValue, templateUrl, absoluteValueOffset, tokens, 0 35084 /* ParseFlags.None */ 35085 , this.errors, 0 35086 /* relative offset */ 35087 ); 35088 return parser.parseTemplateBindings({ 35089 source: templateKey, 35090 span: new AbsoluteSourceSpan(absoluteKeyOffset, absoluteKeyOffset + templateKey.length) 35091 }); 35092 } 35093 35094 parseInterpolation(input, location, absoluteOffset, interpolatedTokens, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) { 35095 const { 35096 strings, 35097 expressions, 35098 offsets 35099 } = this.splitInterpolation(input, location, interpolatedTokens, interpolationConfig); 35100 if (expressions.length === 0) return null; 35101 const expressionNodes = []; 35102 35103 for (let i = 0; i < expressions.length; ++i) { 35104 const expressionText = expressions[i].text; 35105 35106 const sourceToLex = this._stripComments(expressionText); 35107 35108 const tokens = this._lexer.tokenize(sourceToLex); 35109 35110 const ast = new _ParseAST(input, location, absoluteOffset, tokens, 0 35111 /* ParseFlags.None */ 35112 , this.errors, offsets[i]).parseChain(); 35113 expressionNodes.push(ast); 35114 } 35115 35116 return this.createInterpolationAst(strings.map(s => s.text), expressionNodes, input, location, absoluteOffset); 35117 } 35118 /** 35119 * Similar to `parseInterpolation`, but treats the provided string as a single expression 35120 * element that would normally appear within the interpolation prefix and suffix (`{{` and `}}`). 35121 * This is used for parsing the switch expression in ICUs. 35122 */ 35123 35124 35125 parseInterpolationExpression(expression, location, absoluteOffset) { 35126 const sourceToLex = this._stripComments(expression); 35127 35128 const tokens = this._lexer.tokenize(sourceToLex); 35129 35130 const ast = new _ParseAST(expression, location, absoluteOffset, tokens, 0 35131 /* ParseFlags.None */ 35132 , this.errors, 0).parseChain(); 35133 const strings = ['', '']; // The prefix and suffix strings are both empty 35134 35135 return this.createInterpolationAst(strings, [ast], expression, location, absoluteOffset); 35136 } 35137 35138 createInterpolationAst(strings, expressions, input, location, absoluteOffset) { 35139 const span = new ParseSpan(0, input.length); 35140 const interpolation = new Interpolation(span, span.toAbsolute(absoluteOffset), strings, expressions); 35141 return new ASTWithSource(interpolation, input, location, absoluteOffset, this.errors); 35142 } 35143 /** 35144 * Splits a string of text into "raw" text segments and expressions present in interpolations in 35145 * the string. 35146 * Returns `null` if there are no interpolations, otherwise a 35147 * `SplitInterpolation` with splits that look like 35148 * <raw text> <expression> <raw text> ... <raw text> <expression> <raw text> 35149 */ 35150 35151 35152 splitInterpolation(input, location, interpolatedTokens, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) { 35153 const strings = []; 35154 const expressions = []; 35155 const offsets = []; 35156 const inputToTemplateIndexMap = interpolatedTokens ? getIndexMapForOriginalTemplate(interpolatedTokens) : null; 35157 let i = 0; 35158 let atInterpolation = false; 35159 let extendLastString = false; 35160 let { 35161 start: interpStart, 35162 end: interpEnd 35163 } = interpolationConfig; 35164 35165 while (i < input.length) { 35166 if (!atInterpolation) { 35167 // parse until starting {{ 35168 const start = i; 35169 i = input.indexOf(interpStart, i); 35170 35171 if (i === -1) { 35172 i = input.length; 35173 } 35174 35175 const text = input.substring(start, i);
35176 strings.push({ 35177 text, 35178 start, 35179 end: i 35180 }); 35181 atInterpolation = true; 35182 } else { 35183 // parse from starting {{ to ending }} while ignoring content inside quotes. 35184 const fullStart = i; 35185 const exprStart = fullStart + interpStart.length; 35186 35187 const exprEnd = this._getInterpolationEndIndex(input, interpEnd, exprStart); 35188 35189 if (exprEnd === -1) { 35190 // Could not find the end of the interpolation; do not parse an expression. 35191 // Instead we should extend the content on the last raw string. 35192 atInterpolation = false; 35193 extendLastString = true; 35194 break; 35195 } 35196 35197 const fullEnd = exprEnd + interpEnd.length; 35198 const text = input.substring(exprStart, exprEnd); 35199 35200 if (text.trim().length === 0) { 35201 this._reportError('Blank expressions are not allowed in interpolated strings', input, `at column ${i} in`, location); 35202 } 35203 35204 expressions.push({ 35205 text, 35206 start: fullStart, 35207 end: fullEnd 35208 }); 35209 const startInOriginalTemplate = inputToTemplateIndexMap?.get(fullStart) ?? fullStart; 35210 const offset = startInOriginalTemplate + interpStart.length; 35211 offsets.push(offset); 35212 i = fullEnd; 35213 atInterpolation = false; 35214 } 35215 } 35216 35217 if (!atInterpolation) { 35218 // If we are now at a text section, add the remaining content as a raw string. 35219 if (extendLastString) { 35220 const piece = strings[strings.length - 1]; 35221 piece.text += input.substring(i); 35222 piece.end = input.length; 35223 } else { 35224 strings.push({ 35225 text: input.substring(i), 35226 start: i, 35227 end: input.length 35228 }); 35229 } 35230 } 35231 35232 return new SplitInterpolation(strings, expressions, offsets); 35233 } 35234 35235 wrapLiteralPrimitive(input, location, absoluteOffset) { 35236 const span = new ParseSpan(0, input == null ? 0 : input.length); 35237 return new ASTWithSource(new LiteralPrimitive(span, span.toAbsolute(absoluteOffset), input), input, location, absoluteOffset, this.errors); 35238 } 35239 35240 _stripComments(input) { 35241 const i = this._commentStart(input); 35242 35243 return i != null ? input.substring(0, i) : input; 35244 } 35245 35246 _commentStart(input) { 35247 let outerQuote = null; 35248 35249 for (let i = 0; i < input.length - 1; i++) { 35250 const char = input.charCodeAt(i); 35251 const nextChar = input.charCodeAt(i + 1); 35252 if (char === $SLASH && nextChar == $SLASH && outerQuote == null) return i; 35253 35254 if (outerQuote === char) { 35255 outerQuote = null; 35256 } else if (outerQuote == null && isQuote(char)) { 35257 outerQuote = char; 35258 } 35259 } 35260 35261 return null; 35262 } 35263 35264 _checkNoInterpolation(input, location, { 35265 start, 35266 end 35267 }) { 35268 let startIndex = -1; 35269 let endIndex = -1; 35270 35271 for (const charIndex of this._forEachUnquotedChar(input, 0)) { 35272 if (startIndex === -1) { 35273 if (input.startsWith(start)) { 35274 startIndex = charIndex; 35275 } 35276 } else { 35277 endIndex = this._getInterpolationEndIndex(input, end, charIndex); 35278 35279 if (endIndex > -1) { 35280 break; 35281 } 35282 } 35283 } 35284 35285 if (startIndex > -1 && endIndex > -1) { 35286 this._reportError(`Got interpolation (${start}${end}) where expression was expected`, input, `at column ${startIndex} in`, location); 35287 } 35288 } 35289 /** 35290 * Finds the index of the end of an interpolation expression 35291 * while ignoring comments and quoted content. 35292 */ 35293 35294 35295 _getInterpolationEndIndex(input, expressionEnd, start) { 35296 for (const charIndex of this._forEachUnquotedChar(input, start)) { 35297 if (input.startsWith(expressionEnd, charIndex)) { 35298 return charIndex; 35299 } // Nothing else in the expression matters after we've 35300 // hit a comment so look directly for the end token. 35301 35302 35303 if (input.startsWith('//', charIndex)) { 35304 return input.indexOf(expressionEnd, charIndex); 35305 } 35306 } 35307 35308 return -1; 35309 } 35310 /** 35311 * Generator used to iterate over the character indexes of a string that are outside of quotes. 35312 * @param input String to loop through. 35313 * @param start Index within the string at which to start. 35314 */ 35315 35316 35317 *_forEachUnquotedChar(input, start) {
35318 let currentQuote = null; 35319 let escapeCount = 0; 35320 35321 for (let i = start; i < input.length; i++) { 35322 const char = input[i]; // Skip the characters inside quotes. Note that we only care about the outer-most 35323 // quotes matching up and we need to account for escape characters. 35324 35325 if (isQuote(input.charCodeAt(i)) && (currentQuote === null || currentQuote === char) && escapeCount % 2 === 0) { 35326 currentQuote = currentQuote === null ? char : null; 35327 } else if (currentQuote === null) { 35328 yield i; 35329 } 35330 35331 escapeCount = char === '\\' ? escapeCount + 1 : 0; 35332 } 35333 } 35334 35335} 35336/** Describes a stateful context an expression parser is in. */ 35337 35338 35339var ParseContextFlags; 35340 35341(function (ParseContextFlags) { 35342 ParseContextFlags[ParseContextFlags["None"] = 0] = "None"; 35343 /** 35344 * A Writable context is one in which a value may be written to an lvalue. 35345 * For example, after we see a property access, we may expect a write to the 35346 * property via the "=" operator. 35347 * prop 35348 * ^ possible "=" after 35349 */ 35350 35351 ParseContextFlags[ParseContextFlags["Writable"] = 1] = "Writable"; 35352})(ParseContextFlags || (ParseContextFlags = {})); 35353 35354class _ParseAST { 35355 constructor(input, location, absoluteOffset, tokens, parseFlags, errors, offset) { 35356 this.input = input; 35357 this.location = location; 35358 this.absoluteOffset = absoluteOffset; 35359 this.tokens = tokens; 35360 this.parseFlags = parseFlags; 35361 this.errors = errors; 35362 this.offset = offset; 35363 this.rparensExpected = 0; 35364 this.rbracketsExpected = 0; 35365 this.rbracesExpected = 0; 35366 this.context = ParseContextFlags.None; // Cache of expression start and input indeces to the absolute source span they map to, used to 35367 // prevent creating superfluous source spans in `sourceSpan`. 35368 // A serial of the expression start and input index is used for mapping because both are stateful 35369 // and may change for subsequent expressions visited by the parser. 35370 35371 this.sourceSpanCache = new Map(); 35372 this.index = 0; 35373 } 35374 35375 peek(offset) { 35376 const i = this.index + offset; 35377 return i < this.tokens.length ? this.tokens[i] : EOF; 35378 } 35379 35380 get next() { 35381 return this.peek(0); 35382 } 35383 /** Whether all the parser input has been processed. */ 35384 35385 35386 get atEOF() { 35387 return this.index >= this.tokens.length; 35388 } 35389 /** 35390 * Index of the next token to be processed, or the end of the last token if all have been 35391 * processed. 35392 */ 35393 35394 35395 get inputIndex() { 35396 return this.atEOF ? this.currentEndIndex : this.next.index + this.offset; 35397 } 35398 /** 35399 * End index of the last processed token, or the start of the first token if none have been 35400 * processed. 35401 */ 35402 35403 35404 get currentEndIndex() { 35405 if (this.index > 0) { 35406 const curToken = this.peek(-1); 35407 return curToken.end + this.offset; 35408 } // No tokens have been processed yet; return the next token's start or the length of the input 35409 // if there is no token. 35410 35411 35412 if (this.tokens.length === 0) { 35413 return this.input.length + this.offset; 35414 } 35415 35416 return this.next.index + this.offset; 35417 } 35418 /** 35419 * Returns the absolute offset of the start of the current token. 35420 */ 35421 35422 35423 get currentAbsoluteOffset() { 35424 return this.absoluteOffset + this.inputIndex; 35425 } 35426 /** 35427 * Retrieve a `ParseSpan` from `start` to the current position (or to `artificialEndIndex` if 35428 * provided). 35429 * 35430 * @param start Position from which the `ParseSpan` will start. 35431 * @param artificialEndIndex Optional ending index to be used if provided (and if greater than the 35432 * natural ending index) 35433 */ 35434 35435 35436 span(start, artificialEndIndex) { 35437 let endIndex = this.currentEndIndex; 35438 35439 if (artificialEndIndex !== undefined && artificialEndIndex > this.currentEndIndex) { 35440 endIndex = artificialEndIndex; 35441 } // In some unusual parsing scenarios (like when certain tokens are missing and an `EmptyExpr` is 35442 // being created), the current token may already be advanced beyond the `currentEndIndex`. This 35443 // appears to be a deep-seated parser bug. 35444 // 35445 // As a workaround for now, swap the start and end indices to ensure a valid `ParseSpan`. 35446 // TODO(alxhub): fix the bug upstream in the parser state, and remove this workaround. 35447 35448 35449 if (start > endIndex) { 35450 const tmp = endIndex; 35451 endIndex = start; 35452 start = tmp; 35453 } 35454 35455 return new ParseSpan(start, endIndex); 35456 } 35457 35458 sourceSpan(start, artificialEndIndex) { 35459 const serial = `${start}@${this.inputIndex}:${artificialEndIndex}`; 35460 35461 if (!this.sourceSpanCache.has(serial)) { 35462 this.sourceSpanCache.set(serial, this.span(start, artificialEndIndex).toAbsolute(this.absoluteOffset)); 35463 } 35464 35465 return this.sourceSpanCache.get(serial); 35466 } 35467 35468 advance() { 35469 this.index++; 35470 } 35471 /** 35472 * Executes a callback in the provided context. 35473 */ 35474 35475 35476 withContext(context, cb) { 35477 this.context |= context; 35478 const ret = cb(); 35479 this.context ^= context; 35480 return ret; 35481 } 35482 35483 consumeOptionalCharacter(code) { 35484 if (this.next.isCharacter(code)) { 35485 this.advance(); 35486 return true; 35487 } else { 35488 return false;
35489 } 35490 } 35491 35492 peekKeywordLet() { 35493 return this.next.isKeywordLet(); 35494 } 35495 35496 peekKeywordAs() { 35497 return this.next.isKeywordAs(); 35498 } 35499 /** 35500 * Consumes an expected character, otherwise emits an error about the missing expected character 35501 * and skips over the token stream until reaching a recoverable point. 35502 * 35503 * See `this.error` and `this.skip` for more details. 35504 */ 35505 35506 35507 expectCharacter(code) { 35508 if (this.consumeOptionalCharacter(code)) return; 35509 this.error(`Missing expected ${String.fromCharCode(code)}`); 35510 } 35511 35512 consumeOptionalOperator(op) { 35513 if (this.next.isOperator(op)) { 35514 this.advance(); 35515 return true; 35516 } else { 35517 return false; 35518 } 35519 } 35520 35521 expectOperator(operator) { 35522 if (this.consumeOptionalOperator(operator)) return; 35523 this.error(`Missing expected operator ${operator}`); 35524 } 35525 35526 prettyPrintToken(tok) { 35527 return tok === EOF ? 'end of input' : `token ${tok}`; 35528 } 35529 35530 expectIdentifierOrKeyword() { 35531 const n = this.next; 35532 35533 if (!n.isIdentifier() && !n.isKeyword()) { 35534 if (n.isPrivateIdentifier()) { 35535 this._reportErrorForPrivateIdentifier(n, 'expected identifier or keyword'); 35536 } else { 35537 this.error(`Unexpected ${this.prettyPrintToken(n)}, expected identifier or keyword`); 35538 } 35539 35540 return null; 35541 } 35542 35543 this.advance(); 35544 return n.toString(); 35545 } 35546 35547 expectIdentifierOrKeywordOrString() { 35548 const n = this.next; 35549 35550 if (!n.isIdentifier() && !n.isKeyword() && !n.isString()) { 35551 if (n.isPrivateIdentifier()) { 35552 this._reportErrorForPrivateIdentifier(n, 'expected identifier, keyword or string'); 35553 } else { 35554 this.error(`Unexpected ${this.prettyPrintToken(n)}, expected identifier, keyword, or string`); 35555 } 35556 35557 return ''; 35558 } 35559 35560 this.advance(); 35561 return n.toString(); 35562 } 35563 35564 parseChain() { 35565 const exprs = []; 35566 const start = this.inputIndex; 35567 35568 while (this.index < this.tokens.length) { 35569 const expr = this.parsePipe(); 35570 exprs.push(expr); 35571 35572 if (this.consumeOptionalCharacter($SEMICOLON)) { 35573 if (!(this.parseFlags & 1 35574 /* ParseFlags.Action */ 35575 )) { 35576 this.error('Binding expression cannot contain chained expression'); 35577 } 35578 35579 while (this.consumeOptionalCharacter($SEMICOLON)) {} // read all semicolons 35580 35581 } else if (this.index < this.tokens.length) { 35582 const errorIndex = this.index; 35583 this.error(`Unexpected token '${this.next}'`); // The `error` call above will skip ahead to the next recovery point in an attempt to 35584 // recover part of the expression, but that might be the token we started from which will 35585 // lead to an infinite loop. If that's the case, break the loop assuming that we can't 35586 // parse further. 35587 35588 if (this.index === errorIndex) { 35589 break; 35590 } 35591 } 35592 } 35593 35594 if (exprs.length === 0) { 35595 // We have no expressions so create an empty expression that spans the entire input length 35596 const artificialStart = this.offset; 35597 const artificialEnd = this.offset + this.input.length; 35598 return new EmptyExpr(this.span(artificialStart, artificialEnd), this.sourceSpan(artificialStart, artificialEnd)); 35599 } 35600 35601 if (exprs.length == 1) return exprs[0]; 35602 return new Chain(this.span(start), this.sourceSpan(start), exprs); 35603 } 35604 35605 parsePipe() { 35606 const start = this.inputIndex; 35607 let result = this.parseExpression(); 35608 35609 if (this.consumeOptionalOperator('|')) { 35610 if (this.parseFlags & 1 35611 /* ParseFlags.Action */ 35612 ) { 35613 this.error('Cannot have a pipe in an action expression'); 35614 } 35615 35616 do { 35617 const nameStart = this.inputIndex; 35618 let nameId = this.expectIdentifierOrKeyword(); 35619 let nameSpan; 35620 let fullSpanEnd = undefined; 35621 35622 if (nameId !== null) { 35623 nameSpan = this.sourceSpan(nameStart); 35624 } else { 35625 // No valid identifier was found, so we'll assume an empty pipe name (''). 35626 nameId = ''; // However, there may have been whitespace present between the pipe character and the next 35627 // token in the sequence (or the end of input). We want to track this whitespace so that 35628 // the `BindingPipe` we produce covers not just the pipe character, but any trailing 35629 // whitespace beyond it. Another way of thinking about this is that the zero-length name 35630 // is assumed to be at the end of any whitespace beyond the pipe character. 35631 // 35632 // Therefore, we push the end of the `ParseSpan` for this pipe all the way up to the 35633 // beginning of the next token, or until the end of input if the next token is EOF.
35634 35635 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 35636 // beyond the pipe character. 35637 35638 nameSpan = new ParseSpan(fullSpanEnd, fullSpanEnd).toAbsolute(this.absoluteOffset); 35639 } 35640 35641 const args = []; 35642 35643 while (this.consumeOptionalCharacter($COLON)) { 35644 args.push(this.parseExpression()); // If there are additional expressions beyond the name, then the artificial end for the 35645 // name is no longer relevant. 35646 } 35647 35648 result = new BindingPipe(this.span(start), this.sourceSpan(start, fullSpanEnd), result, nameId, args, nameSpan); 35649 } while (this.consumeOptionalOperator('|')); 35650 } 35651 35652 return result; 35653 } 35654 35655 parseExpression() { 35656 return this.parseConditional(); 35657 } 35658 35659 parseConditional() { 35660 const start = this.inputIndex; 35661 const result = this.parseLogicalOr(); 35662 35663 if (this.consumeOptionalOperator('?')) { 35664 const yes = this.parsePipe(); 35665 let no; 35666 35667 if (!this.consumeOptionalCharacter($COLON)) { 35668 const end = this.inputIndex; 35669 const expression = this.input.substring(start, end); 35670 this.error(`Conditional expression ${expression} requires all 3 expressions`); 35671 no = new EmptyExpr(this.span(start), this.sourceSpan(start)); 35672 } else { 35673 no = this.parsePipe(); 35674 } 35675 35676 return new Conditional(this.span(start), this.sourceSpan(start), result, yes, no); 35677 } else { 35678 return result; 35679 } 35680 } 35681 35682 parseLogicalOr() { 35683 // '||' 35684 const start = this.inputIndex; 35685 let result = this.parseLogicalAnd(); 35686 35687 while (this.consumeOptionalOperator('||')) { 35688 const right = this.parseLogicalAnd(); 35689 result = new Binary(this.span(start), this.sourceSpan(start), '||', result, right); 35690 } 35691 35692 return result; 35693 } 35694 35695 parseLogicalAnd() { 35696 // '&&' 35697 const start = this.inputIndex; 35698 let result = this.parseNullishCoalescing(); 35699 35700 while (this.consumeOptionalOperator('&&')) { 35701 const right = this.parseNullishCoalescing(); 35702 result = new Binary(this.span(start), this.sourceSpan(start), '&&', result, right); 35703 } 35704 35705 return result; 35706 } 35707 35708 parseNullishCoalescing() { 35709 // '??' 35710 const start = this.inputIndex; 35711 let result = this.parseEquality(); 35712 35713 while (this.consumeOptionalOperator('??')) { 35714 const right = this.parseEquality(); 35715 result = new Binary(this.span(start), this.sourceSpan(start), '??', result, right); 35716 } 35717 35718 return result; 35719 } 35720 35721 parseEquality() { 35722 // '==','!=','===','!==' 35723 const start = this.inputIndex; 35724 let result = this.parseRelational(); 35725 35726 while (this.next.type == TokenType.Operator) { 35727 const operator = this.next.strValue; 35728 35729 switch (operator) { 35730 case '==': 35731 case '===': 35732 case '!=': 35733 case '!==': 35734 this.advance(); 35735 const right = this.parseRelational(); 35736 result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right); 35737 continue; 35738 } 35739 35740 break; 35741 } 35742 35743 return result; 35744 } 35745 35746 parseRelational() { 35747 // '<', '>', '<=', '>=' 35748 const start = this.inputIndex; 35749 let result = this.parseAdditive(); 35750 35751 while (this.next.type == TokenType.Operator) { 35752 const operator = this.next.strValue; 35753 35754 switch (operator) { 35755 case '<': 35756 case '>': 35757 case '<=': 35758 case '>=': 35759 this.advance(); 35760 const right = this.parseAdditive(); 35761 result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right); 35762 continue; 35763 } 35764 35765 break; 35766 } 35767 35768 return result; 35769 } 35770 35771 parseAdditive() { 35772 // '+', '-' 35773 const start = this.inputIndex; 35774 let result = this.parseMultiplicative(); 35775 35776 while (this.next.type == TokenType.Operator) { 35777 const operator = this.next.strValue; 35778 35779 switch (operator) { 35780 case '+': 35781 case '-': 35782 this.advance(); 35783 let right = this.parseMultiplicative(); 35784 result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right); 35785 continue; 35786 } 35787 35788 break; 35789 } 35790 35791 return result; 35792 } 35793 35794 parseMultiplicative() { 35795 // '*', '%', '/' 35796 const start = this.inputIndex; 35797 let result = this.parsePrefix(); 35798 35799 while (this.next.type == TokenType.Operator) { 35800 const operator = this.next.strValue; 35801 35802 switch (operator) { 35803 case '*': 35804 case '%': 35805 case '/': 35806 this.advance(); 35807 let right = this.parsePrefix(); 35808 result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right); 35809 continue; 35810 } 35811 35812 break; 35813 } 35814 35815 return result; 35816 } 35817 35818 parsePrefix() { 35819 if (this.next.type == TokenType.Operator) { 35820 const start = this.inputIndex; 35821 const operator = this.next.strValue; 35822 let result; 35823 35824 switch (operator) { 35825 case '+': 35826 this.advance(); 35827 result = this.parsePrefix(); 35828 return Unary.createPlus(this.span(start), this.sourceSpan(start), result); 35829 35830 case '-': 35831 this.advance(); 35832 result = this.parsePrefix(); 35833 return Unary.createMinus(this.span(start), this.sourceSpan(start), result); 35834 35835 case '!': 35836 this.advance(); 35837 result = this.parsePrefix(); 35838 return new PrefixNot(this.span(start), this.sourceSpan(start), result); 35839 } 35840 } 35841 35842 return this.parseCallChain(); 35843 } 35844 35845 parseCallChain() { 35846 const start = this.inputIndex; 35847 let result = this.parsePrimary(); 35848 35849 while (true) { 35850 if (this.consumeOptionalCharacter($PERIOD)) { 35851 result = this.parseAccessMember(result, start, false); 35852 } else if (this.consumeOptionalOperator('?.')) { 35853 if (this.consumeOptionalCharacter($LPAREN)) { 35854 result = this.parseCall(result, start, true); 35855 } else { 35856 result = this.consumeOptionalCharacter($LBRACKET) ? this.parseKeyedReadOrWrite(result, start, true) : this.parseAccessMember(result, start, true); 35857 } 35858 } else if (this.consumeOptionalCharacter($LBRACKET)) { 35859 result = this.parseKeyedReadOrWrite(result, start, false); 35860 } else if (this.consumeOptionalCharacter($LPAREN)) { 35861 result = this.parseCall(result, start, false); 35862 } else if (this.consumeOptionalOperator('!')) { 35863 result = new NonNullAssert(this.span(start), this.sourceSpan(start), result); 35864 } else { 35865 return result; 35866 } 35867 } 35868 } 35869 35870 parsePrimary() { 35871 const start = this.inputIndex; 35872 35873 if (this.consumeOptionalCharacter($LPAREN)) { 35874 this.rparensExpected++; 35875 const result = this.parsePipe(); 35876 this.rparensExpected--; 35877 this.expectCharacter($RPAREN); 35878 return result; 35879 } else if (this.next.isKeywordNull()) { 35880 this.advance(); 35881 return new LiteralPrimitive(this.span(start), this.sourceSpan(start), null); 35882 } else if (this.next.isKeywordUndefined()) { 35883 this.advance(); 35884 return new LiteralPrimitive(this.span(start), this.sourceSpan(start), void 0); 35885 } else if (this.next.isKeywordTrue()) { 35886 this.advance(); 35887 return new LiteralPrimitive(this.span(start), this.sourceSpan(start), true); 35888 } else if (this.next.isKeywordFalse()) { 35889 this.advance(); 35890 return new LiteralPrimitive(this.span(start), this.sourceSpan(start), false); 35891 } else if (this.next.isKeywordThis()) { 35892 this.advance(); 35893 return new ThisReceiver(this.span(start), this.sourceSpan(start)); 35894 } else if (this.consumeOptionalCharacter($LBRACKET)) { 35895 this.rbracketsExpected++; 35896 const elements = this.parseExpressionList($RBRACKET); 35897 this.rbracketsExpected--; 35898 this.expectCharacter($RBRACKET); 35899 return new LiteralArray(this.span(start), this.sourceSpan(start), elements); 35900 } else if (this.next.isCharacter($LBRACE)) { 35901 return this.parseLiteralMap(); 35902 } else if (this.next.isIdentifier()) { 35903 return this.parseAccessMember(new ImplicitReceiver(this.span(start), this.sourceSpan(start)), start, false); 35904 } else if (this.next.isNumber()) { 35905 const value = this.next.toNumber(); 35906 this.advance(); 35907 return new LiteralPrimitive(this.span(start), this.sourceSpan(start), value); 35908 } else if (this.next.isString()) { 35909 const literalValue = this.next.toString(); 35910 this.advance(); 35911 return new LiteralPrimitive(this.span(start), this.sourceSpan(start), literalValue); 35912 } else if (this.next.isPrivateIdentifier()) { 35913 this._reportErrorForPrivateIdentifier(this.next, null); 35914 35915 return new EmptyExpr(this.span(start), this.sourceSpan(start)); 35916 } else if (this.index >= this.tokens.length) { 35917 this.error(`Unexpected end of expression: ${this.input}`); 35918 return new EmptyExpr(this.span(start), this.sourceSpan(start)); 35919 } else { 35920 this.error(`Unexpected token ${this.next}`); 35921 return new EmptyExpr(this.span(start), this.sourceSpan(start)); 35922 } 35923 } 35924 35925 parseExpressionList(terminator) { 35926 const result = []; 35927 35928 do { 35929 if (!this.next.isCharacter(terminator)) { 35930 result.push(this.parsePipe()); 35931 } else { 35932 break; 35933 } 35934 } while (this.consumeOptionalCharacter($COMMA)); 35935 35936 return result; 35937 } 35938 35939 parseLiteralMap() {
35940 const keys = []; 35941 const values = []; 35942 const start = this.inputIndex; 35943 this.expectCharacter($LBRACE); 35944 35945 if (!this.consumeOptionalCharacter($RBRACE)) { 35946 this.rbracesExpected++; 35947 35948 do { 35949 const keyStart = this.inputIndex; 35950 const quoted = this.next.isString(); 35951 const key = this.expectIdentifierOrKeywordOrString(); 35952 keys.push({ 35953 key, 35954 quoted 35955 }); // Properties with quoted keys can't use the shorthand syntax. 35956 35957 if (quoted) { 35958 this.expectCharacter($COLON); 35959 values.push(this.parsePipe()); 35960 } else if (this.consumeOptionalCharacter($COLON)) { 35961 values.push(this.parsePipe()); 35962 } else { 35963 const span = this.span(keyStart); 35964 const sourceSpan = this.sourceSpan(keyStart); 35965 values.push(new PropertyRead(span, sourceSpan, sourceSpan, new ImplicitReceiver(span, sourceSpan), key)); 35966 } 35967 } while (this.consumeOptionalCharacter($COMMA)); 35968 35969 this.rbracesExpected--; 35970 this.expectCharacter($RBRACE); 35971 } 35972 35973 return new LiteralMap(this.span(start), this.sourceSpan(start), keys, values); 35974 } 35975 35976 parseAccessMember(readReceiver, start, isSafe) { 35977 const nameStart = this.inputIndex; 35978 const id = this.withContext(ParseContextFlags.Writable, () => { 35979 const id = this.expectIdentifierOrKeyword() ?? ''; 35980 35981 if (id.length === 0) { 35982 this.error(`Expected identifier for property access`, readReceiver.span.end); 35983 } 35984 35985 return id; 35986 }); 35987 const nameSpan = this.sourceSpan(nameStart); 35988 let receiver; 35989 35990 if (isSafe) { 35991 if (this.consumeOptionalAssignment()) { 35992 this.error('The \'?.\' operator cannot be used in the assignment'); 35993 receiver = new EmptyExpr(this.span(start), this.sourceSpan(start)); 35994 } else { 35995 receiver = new SafePropertyRead(this.span(start), this.sourceSpan(start), nameSpan, readReceiver, id); 35996 } 35997 } else { 35998 if (this.consumeOptionalAssignment()) { 35999 if (!(this.parseFlags & 1 36000 /* ParseFlags.Action */ 36001 )) { 36002 this.error('Bindings cannot contain assignments'); 36003 return new EmptyExpr(this.span(start), this.sourceSpan(start)); 36004 } 36005 36006 const value = this.parseConditional(); 36007 receiver = new PropertyWrite(this.span(start), this.sourceSpan(start), nameSpan, readReceiver, id, value); 36008 } else { 36009 receiver = new PropertyRead(this.span(start), this.sourceSpan(start), nameSpan, readReceiver, id); 36010 } 36011 } 36012 36013 return receiver; 36014 } 36015 36016 parseCall(receiver, start, isSafe) { 36017 const argumentStart = this.inputIndex; 36018 this.rparensExpected++; 36019 const args = this.parseCallArguments(); 36020 const argumentSpan = this.span(argumentStart, this.inputIndex).toAbsolute(this.absoluteOffset); 36021 this.expectCharacter($RPAREN); 36022 this.rparensExpected--; 36023 const span = this.span(start); 36024 const sourceSpan = this.sourceSpan(start); 36025 return isSafe ? new SafeCall(span, sourceSpan, receiver, args, argumentSpan) : new Call(span, sourceSpan, receiver, args, argumentSpan); 36026 } 36027 36028 consumeOptionalAssignment() { 36029 // When parsing assignment events (originating from two-way-binding aka banana-in-a-box syntax), 36030 // it is valid for the primary expression to be terminated by the non-null operator. This 36031 // primary expression is substituted as LHS of the assignment operator to achieve 36032 // two-way-binding, such that the LHS could be the non-null operator. The grammar doesn't 36033 // naturally allow for this syntax, so assignment events are parsed specially. 36034 if (this.parseFlags & 2 36035 /* ParseFlags.AssignmentEvent */ 36036 && this.next.isOperator('!') && this.peek(1).isOperator('=')) { 36037 // First skip over the ! operator. 36038 this.advance(); // Then skip over the = operator, to fully consume the optional assignment operator. 36039 36040 this.advance(); 36041 return true; 36042 } 36043 36044 return this.consumeOptionalOperator('='); 36045 } 36046 36047 parseCallArguments() { 36048 if (this.next.isCharacter($RPAREN)) return []; 36049 const positionals = []; 36050 36051 do { 36052 positionals.push(this.parsePipe()); 36053 } while (this.consumeOptionalCharacter($COMMA)); 36054 36055 return positionals; 36056 } 36057 /** 36058 * Parses an identifier, a keyword, a string with an optional `-` in between, 36059 * and returns the string along with its absolute source span. 36060 */ 36061 36062 36063 expectTemplateBindingKey() { 36064 let result = ''; 36065 let operatorFound = false;
36066 const start = this.currentAbsoluteOffset; 36067 36068 do { 36069 result += this.expectIdentifierOrKeywordOrString(); 36070 operatorFound = this.consumeOptionalOperator('-'); 36071 36072 if (operatorFound) { 36073 result += '-'; 36074 } 36075 } while (operatorFound); 36076 36077 return { 36078 source: result, 36079 span: new AbsoluteSourceSpan(start, start + result.length) 36080 }; 36081 } 36082 /** 36083 * Parse microsyntax template expression and return a list of bindings or 36084 * parsing errors in case the given expression is invalid. 36085 * 36086 * For example, 36087 * ``` 36088 * <div *ngFor="let item of items; index as i; trackBy: func"> 36089 * ``` 36090 * contains five bindings: 36091 * 1. ngFor -> null 36092 * 2. item -> NgForOfContext.$implicit 36093 * 3. ngForOf -> items 36094 * 4. i -> NgForOfContext.index 36095 * 5. ngForTrackBy -> func 36096 * 36097 * For a full description of the microsyntax grammar, see 36098 * https://gist.github.com/mhevery/d3530294cff2e4a1b3fe15ff75d08855 36099 * 36100 * @param templateKey name of the microsyntax directive, like ngIf, ngFor, 36101 * without the *, along with its absolute span. 36102 */ 36103 36104 36105 parseTemplateBindings(templateKey) { 36106 const bindings = []; // The first binding is for the template key itself 36107 // In *ngFor="let item of items", key = "ngFor", value = null 36108 // In *ngIf="cond | pipe", key = "ngIf", value = "cond | pipe" 36109 36110 bindings.push(...this.parseDirectiveKeywordBindings(templateKey)); 36111 36112 while (this.index < this.tokens.length) { 36113 // If it starts with 'let', then this must be variable declaration 36114 const letBinding = this.parseLetBinding(); 36115 36116 if (letBinding) { 36117 bindings.push(letBinding); 36118 } else { 36119 // Two possible cases here, either `value "as" key` or 36120 // "directive-keyword expression". We don't know which case, but both 36121 // "value" and "directive-keyword" are template binding key, so consume 36122 // the key first. 36123 const key = this.expectTemplateBindingKey(); // Peek at the next token, if it is "as" then this must be variable 36124 // declaration. 36125 36126 const binding = this.parseAsBinding(key); 36127 36128 if (binding) { 36129 bindings.push(binding); 36130 } else { 36131 // Otherwise the key must be a directive keyword, like "of". Transform 36132 // the key to actual key. Eg. of -> ngForOf, trackBy -> ngForTrackBy 36133 key.source = templateKey.source + key.source.charAt(0).toUpperCase() + key.source.substring(1); 36134 bindings.push(...this.parseDirectiveKeywordBindings(key)); 36135 } 36136 } 36137 36138 this.consumeStatementTerminator(); 36139 } 36140 36141 return new TemplateBindingParseResult(bindings, [] 36142 /* warnings */ 36143 , this.errors); 36144 } 36145 36146 parseKeyedReadOrWrite(receiver, start, isSafe) { 36147 return this.withContext(ParseContextFlags.Writable, () => { 36148 this.rbracketsExpected++; 36149 const key = this.parsePipe(); 36150 36151 if (key instanceof EmptyExpr) { 36152 this.error(`Key access cannot be empty`); 36153 } 36154 36155 this.rbracketsExpected--; 36156 this.expectCharacter($RBRACKET); 36157 36158 if (this.consumeOptionalOperator('=')) { 36159 if (isSafe) { 36160 this.error('The \'?.\' operator cannot be used in the assignment'); 36161 } else { 36162 const value = this.parseConditional(); 36163 return new KeyedWrite(this.span(start), this.sourceSpan(start), receiver, key, value); 36164 } 36165 } else { 36166 return isSafe ? new SafeKeyedRead(this.span(start), this.sourceSpan(start), receiver, key) : new KeyedRead(this.span(start), this.sourceSpan(start), receiver, key); 36167 } 36168 36169 return new EmptyExpr(this.span(start), this.sourceSpan(start)); 36170 }); 36171 } 36172 /** 36173 * Parse a directive keyword, followed by a mandatory expression. 36174 * For example, "of items", "trackBy: func". 36175 * The bindings are: ngForOf -> items, ngForTrackBy -> func 36176 * There could be an optional "as" binding that follows the expression. 36177 * For example, 36178 * ``` 36179 * *ngFor="let item of items | slice:0:1 as collection". 36180 * ^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ 36181 * keyword bound target optional 'as' binding 36182 * ``` 36183 * 36184 * @param key binding key, for example, ngFor, ngIf, ngForOf, along with its 36185 * absolute span. 36186 */ 36187 36188 36189 parseDirectiveKeywordBindings(key) { 36190 const bindings = []; 36191 this.consumeOptionalCharacter($COLON); // trackBy: trackByFunction 36192 36193 const value = this.getDirectiveBoundTarget(); 36194 let spanEnd = this.currentAbsoluteOffset; // The binding could optionally be followed by "as". For example, 36195 // *ngIf="cond | pipe as x". In this case, the key in the "as" binding 36196 // is "x" and the value is the template key itself ("ngIf"). Note that the 36197 // 'key' in the current context now becomes the "value" in the next binding. 36198
36199 const asBinding = this.parseAsBinding(key); 36200 36201 if (!asBinding) { 36202 this.consumeStatementTerminator(); 36203 spanEnd = this.currentAbsoluteOffset; 36204 } 36205 36206 const sourceSpan = new AbsoluteSourceSpan(key.span.start, spanEnd); 36207 bindings.push(new ExpressionBinding(sourceSpan, key, value)); 36208 36209 if (asBinding) { 36210 bindings.push(asBinding); 36211 } 36212 36213 return bindings; 36214 } 36215 /** 36216 * Return the expression AST for the bound target of a directive keyword 36217 * binding. For example, 36218 * ``` 36219 * *ngIf="condition | pipe" 36220 * ^^^^^^^^^^^^^^^^ bound target for "ngIf" 36221 * *ngFor="let item of items" 36222 * ^^^^^ bound target for "ngForOf" 36223 * ``` 36224 */ 36225 36226 36227 getDirectiveBoundTarget() { 36228 if (this.next === EOF || this.peekKeywordAs() || this.peekKeywordLet()) { 36229 return null; 36230 } 36231 36232 const ast = this.parsePipe(); // example: "condition | async" 36233 36234 const { 36235 start, 36236 end 36237 } = ast.span; 36238 const value = this.input.substring(start, end); 36239 return new ASTWithSource(ast, value, this.location, this.absoluteOffset + start, this.errors); 36240 } 36241 /** 36242 * Return the binding for a variable declared using `as`. Note that the order 36243 * of the key-value pair in this declaration is reversed. For example, 36244 * ``` 36245 * *ngFor="let item of items; index as i" 36246 * ^^^^^ ^ 36247 * value key 36248 * ``` 36249 * 36250 * @param value name of the value in the declaration, "ngIf" in the example 36251 * above, along with its absolute span. 36252 */ 36253 36254 36255 parseAsBinding(value) { 36256 if (!this.peekKeywordAs()) { 36257 return null; 36258 } 36259 36260 this.advance(); // consume the 'as' keyword 36261 36262 const key = this.expectTemplateBindingKey(); 36263 this.consumeStatementTerminator(); 36264 const sourceSpan = new AbsoluteSourceSpan(value.span.start, this.currentAbsoluteOffset); 36265 return new VariableBinding(sourceSpan, key, value); 36266 } 36267 /** 36268 * Return the binding for a variable declared using `let`. For example, 36269 * ``` 36270 * *ngFor="let item of items; let i=index;" 36271 * ^^^^^^^^ ^^^^^^^^^^^ 36272 * ``` 36273 * In the first binding, `item` is bound to `NgForOfContext.$implicit`. 36274 * In the second binding, `i` is bound to `NgForOfContext.index`. 36275 */ 36276 36277 36278 parseLetBinding() { 36279 if (!this.peekKeywordLet()) { 36280 return null; 36281 } 36282 36283 const spanStart = this.currentAbsoluteOffset; 36284 this.advance(); // consume the 'let' keyword 36285 36286 const key = this.expectTemplateBindingKey(); 36287 let value = null; 36288 36289 if (this.consumeOptionalOperator('=')) { 36290 value = this.expectTemplateBindingKey(); 36291 } 36292 36293 this.consumeStatementTerminator(); 36294 const sourceSpan = new AbsoluteSourceSpan(spanStart, this.currentAbsoluteOffset); 36295 return new VariableBinding(sourceSpan, key, value); 36296 } 36297 /** 36298 * Consume the optional statement terminator: semicolon or comma. 36299 */ 36300 36301 36302 consumeStatementTerminator() { 36303 this.consumeOptionalCharacter($SEMICOLON) || this.consumeOptionalCharacter($COMMA); 36304 } 36305 /** 36306 * Records an error and skips over the token stream until reaching a recoverable point. See 36307 * `this.skip` for more details on token skipping. 36308 */ 36309 36310 36311 error(message, index = null) { 36312 this.errors.push(new ParserError(message, this.input, this.locationText(index), this.location)); 36313 this.skip(); 36314 } 36315 36316 locationText(index = null) { 36317 if (index == null) index = this.index; 36318 return index < this.tokens.length ? `at column ${this.tokens[index].index + 1} in` : `at the end of the expression`; 36319 } 36320 /** 36321 * Records an error for an unexpected private identifier being discovered. 36322 * @param token Token representing a private identifier. 36323 * @param extraMessage Optional additional message being appended to the error. 36324 */ 36325 36326 36327 _reportErrorForPrivateIdentifier(token, extraMessage) { 36328 let errorMessage = `Private identifiers are not supported. Unexpected private identifier: ${token}`; 36329 36330 if (extraMessage !== null) { 36331 errorMessage += `, ${extraMessage}`; 36332 } 36333 36334 this.error(errorMessage); 36335 } 36336 /** 36337 * Error recovery should skip tokens until it encounters a recovery point. 36338 * 36339 * The following are treated as unconditional recovery points: 36340 * - end of input 36341 * - ';' (parseChain() is always the root production, and it expects a ';') 36342 * - '|' (since pipes may be chained and each pipe expression may be treated independently) 36343 * 36344 * The following are conditional recovery points: 36345 * - ')', '}', ']' if one of calling productions is expecting one of these symbols 36346 * - This allows skip() to recover from errors such as '(a.) + 1' allowing more of the AST to 36347 * be retained (it doesn't skip any tokens as the ')' is retained because of the '(' begins 36348 * an '(' <expr> ')' production). 36349 * The recovery points of grouping symbols must be conditional as they must be skipped if 36350 * none of the calling productions are not expecting the closing token else we will never 36351 * make progress in the case of an extraneous group closing symbol (such as a stray ')'). 36352 * That is, we skip a closing symbol if we are not in a grouping production. 36353 * - '=' in a `Writable` context
36354 * - In this context, we are able to recover after seeing the `=` operator, which 36355 * signals the presence of an independent rvalue expression following the `=` operator. 36356 * 36357 * If a production expects one of these token it increments the corresponding nesting count, 36358 * and then decrements it just prior to checking if the token is in the input. 36359 */ 36360 36361 36362 skip() { 36363 let n = this.next; 36364 36365 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('='))) { 36366 if (this.next.isError()) { 36367 this.errors.push(new ParserError(this.next.toString(), this.input, this.locationText(), this.location)); 36368 } 36369 36370 this.advance(); 36371 n = this.next; 36372 } 36373 } 36374 36375} 36376 36377class SimpleExpressionChecker extends RecursiveAstVisitor { 36378 constructor() { 36379 super(...arguments); 36380 this.errors = []; 36381 } 36382 36383 visitPipe() { 36384 this.errors.push('pipes'); 36385 } 36386 36387} 36388/** 36389 * Computes the real offset in the original template for indexes in an interpolation. 36390 * 36391 * Because templates can have encoded HTML entities and the input passed to the parser at this stage 36392 * of the compiler is the _decoded_ value, we need to compute the real offset using the original 36393 * encoded values in the interpolated tokens. Note that this is only a special case handling for 36394 * `MlParserTokenType.ENCODED_ENTITY` token types. All other interpolated tokens are expected to 36395 * have parts which exactly match the input string for parsing the interpolation. 36396 * 36397 * @param interpolatedTokens The tokens for the interpolated value. 36398 * 36399 * @returns A map of index locations in the decoded template to indexes in the original template 36400 */ 36401 36402 36403function getIndexMapForOriginalTemplate(interpolatedTokens) { 36404 let offsetMap = new Map(); 36405 let consumedInOriginalTemplate = 0; 36406 let consumedInInput = 0; 36407 let tokenIndex = 0; 36408 36409 while (tokenIndex < interpolatedTokens.length) { 36410 const currentToken = interpolatedTokens[tokenIndex]; 36411 36412 if (currentToken.type === 9 36413 /* MlParserTokenType.ENCODED_ENTITY */ 36414 ) { 36415 const [decoded, encoded] = currentToken.parts; 36416 consumedInOriginalTemplate += encoded.length; 36417 consumedInInput += decoded.length; 36418 } else { 36419 const lengthOfParts = currentToken.parts.reduce((sum, current) => sum + current.length, 0); 36420 consumedInInput += lengthOfParts; 36421 consumedInOriginalTemplate += lengthOfParts; 36422 } 36423 36424 offsetMap.set(consumedInInput, consumedInOriginalTemplate); 36425 tokenIndex++; 36426 } 36427 36428 return offsetMap; 36429} 36430/** 36431 * @license 36432 * Copyright Google LLC All Rights Reserved. 36433 * 36434 * Use of this source code is governed by an MIT-style license that can be 36435 * found in the LICENSE file at https://angular.io/license 36436 */ 36437 36438 36439class NodeWithI18n { 36440 constructor(sourceSpan, i18n) { 36441 this.sourceSpan = sourceSpan; 36442 this.i18n = i18n; 36443 } 36444 36445} 36446 36447class Text extends NodeWithI18n { 36448 constructor(value, sourceSpan, tokens, i18n) { 36449 super(sourceSpan, i18n); 36450 this.value = value; 36451 this.tokens = tokens; 36452 } 36453 36454 visit(visitor, context) { 36455 return visitor.visitText(this, context); 36456 } 36457 36458} 36459 36460class Expansion extends NodeWithI18n { 36461 constructor(switchValue, type, cases, sourceSpan, switchValueSourceSpan, i18n) { 36462 super(sourceSpan, i18n); 36463 this.switchValue = switchValue; 36464 this.type = type; 36465 this.cases = cases; 36466 this.switchValueSourceSpan = switchValueSourceSpan; 36467 } 36468 36469 visit(visitor, context) { 36470 return visitor.visitExpansion(this, context); 36471 } 36472 36473} 36474 36475class ExpansionCase { 36476 constructor(value, expression, sourceSpan, valueSourceSpan, expSourceSpan) { 36477 this.value = value; 36478 this.expression = expression; 36479 this.sourceSpan = sourceSpan; 36480 this.valueSourceSpan = valueSourceSpan; 36481 this.expSourceSpan = expSourceSpan; 36482 } 36483 36484 visit(visitor, context) { 36485 return visitor.visitExpansionCase(this, context); 36486 } 36487 36488} 36489 36490class Attribute extends NodeWithI18n { 36491 constructor(name, value, sourceSpan, keySpan, valueSpan, valueTokens, i18n) { 36492 super(sourceSpan, i18n); 36493 this.name = name; 36494 this.value = value; 36495 this.keySpan = keySpan; 36496 this.valueSpan = valueSpan; 36497 this.valueTokens = valueTokens; 36498 } 36499 36500 visit(visitor, context) { 36501 return visitor.visitAttribute(this, context); 36502 } 36503 36504} 36505 36506class Element extends NodeWithI18n { 36507 constructor(name, attrs, children, sourceSpan, startSourceSpan, endSourceSpan = null, i18n) { 36508 super(sourceSpan, i18n); 36509 this.name = name; 36510 this.attrs = attrs; 36511 this.children = children; 36512 this.startSourceSpan = startSourceSpan; 36513 this.endSourceSpan = endSourceSpan; 36514 } 36515 36516 visit(visitor, context) { 36517 return visitor.visitElement(this, context); 36518 } 36519 36520} 36521 36522class Comment {
36523 constructor(value, sourceSpan) { 36524 this.value = value; 36525 this.sourceSpan = sourceSpan; 36526 } 36527 36528 visit(visitor, context) { 36529 return visitor.visitComment(this, context); 36530 } 36531 36532} 36533 36534function visitAll(visitor, nodes, context = null) { 36535 const result = []; 36536 const visit = visitor.visit ? ast => visitor.visit(ast, context) || ast.visit(visitor, context) : ast => ast.visit(visitor, context); 36537 nodes.forEach(ast => { 36538 const astResult = visit(ast); 36539 36540 if (astResult) { 36541 result.push(astResult); 36542 } 36543 }); 36544 return result; 36545} 36546 36547class RecursiveVisitor { 36548 constructor() {} 36549 36550 visitElement(ast, context) { 36551 this.visitChildren(context, visit => { 36552 visit(ast.attrs); 36553 visit(ast.children); 36554 }); 36555 } 36556 36557 visitAttribute(ast, context) {} 36558 36559 visitText(ast, context) {} 36560 36561 visitComment(ast, context) {} 36562 36563 visitExpansion(ast, context) { 36564 return this.visitChildren(context, visit => { 36565 visit(ast.cases); 36566 }); 36567 } 36568 36569 visitExpansionCase(ast, context) {} 36570 36571 visitChildren(context, cb) { 36572 let results = []; 36573 let t = this; 36574 36575 function visit(children) { 36576 if (children) results.push(visitAll(t, children, context)); 36577 } 36578 36579 cb(visit); 36580 return Array.prototype.concat.apply([], results); 36581 } 36582 36583} 36584/** 36585 * @license 36586 * Copyright Google LLC All Rights Reserved. 36587 * 36588 * Use of this source code is governed by an MIT-style license that can be 36589 * found in the LICENSE file at https://angular.io/license 36590 */ 36591// Mapping between all HTML entity names and their unicode representation. 36592// Generated from https://html.spec.whatwg.org/multipage/entities.json by stripping 36593// the `&` and `;` from the keys and removing the duplicates. 36594// see https://www.w3.org/TR/html51/syntax.html#named-character-references 36595 36596 36597const NAMED_ENTITIES = { 36598 'AElig': '\u00C6', 36599 'AMP': '\u0026', 36600 'amp': '\u0026', 36601 'Aacute': '\u00C1', 36602 'Abreve': '\u0102', 36603 'Acirc': '\u00C2', 36604 'Acy': '\u0410', 36605 'Afr': '\uD835\uDD04', 36606 'Agrave': '\u00C0', 36607 'Alpha': '\u0391', 36608 'Amacr': '\u0100', 36609 'And': '\u2A53', 36610 'Aogon': '\u0104', 36611 'Aopf': '\uD835\uDD38', 36612 'ApplyFunction': '\u2061', 36613 'af': '\u2061', 36614 'Aring': '\u00C5', 36615 'angst': '\u00C5', 36616 'Ascr': '\uD835\uDC9C', 36617 'Assign': '\u2254', 36618 'colone': '\u2254', 36619 'coloneq': '\u2254', 36620 'Atilde': '\u00C3', 36621 'Auml': '\u00C4', 36622 'Backslash': '\u2216', 36623 'setminus': '\u2216', 36624 'setmn': '\u2216', 36625 'smallsetminus': '\u2216', 36626 'ssetmn': '\u2216', 36627 'Barv': '\u2AE7', 36628 'Barwed': '\u2306', 36629 'doublebarwedge': '\u2306', 36630 'Bcy': '\u0411', 36631 'Because': '\u2235', 36632 'becaus': '\u2235', 36633 'because': '\u2235', 36634 'Bernoullis': '\u212C', 36635 'Bscr': '\u212C', 36636 'bernou': '\u212C', 36637 'Beta': '\u0392', 36638 'Bfr': '\uD835\uDD05', 36639 'Bopf': '\uD835\uDD39', 36640 'Breve': '\u02D8', 36641 'breve': '\u02D8', 36642 'Bumpeq': '\u224E', 36643 'HumpDownHump': '\u224E', 36644 'bump': '\u224E', 36645 'CHcy': '\u0427', 36646 'COPY': '\u00A9', 36647 'copy': '\u00A9', 36648 'Cacute': '\u0106', 36649 'Cap': '\u22D2', 36650 'CapitalDifferentialD': '\u2145', 36651 'DD': '\u2145', 36652 'Cayleys': '\u212D', 36653 'Cfr': '\u212D', 36654 'Ccaron': '\u010C', 36655 'Ccedil': '\u00C7', 36656 'Ccirc': '\u0108', 36657 'Cconint': '\u2230', 36658 'Cdot': '\u010A', 36659 'Cedilla': '\u00B8', 36660 'cedil': '\u00B8', 36661 'CenterDot': '\u00B7', 36662 'centerdot': '\u00B7', 36663 'middot': '\u00B7', 36664 'Chi': '\u03A7', 36665 'CircleDot': '\u2299', 36666 'odot': '\u2299', 36667 'CircleMinus': '\u2296', 36668 'ominus': '\u2296', 36669 'CirclePlus': '\u2295', 36670 'oplus': '\u2295', 36671 'CircleTimes': '\u2297', 36672 'otimes': '\u2297', 36673 'ClockwiseContourIntegral': '\u2232', 36674 'cwconint': '\u2232', 36675 'CloseCurlyDoubleQuote': '\u201D', 36676 'rdquo': '\u201D', 36677 'rdquor': '\u201D', 36678 'CloseCurlyQuote': '\u2019', 36679 'rsquo': '\u2019', 36680 'rsquor': '\u2019', 36681 'Colon': '\u2237', 36682 'Proportion': '\u2237', 36683 'Colone': '\u2A74', 36684 'Congruent': '\u2261', 36685 'equiv': '\u2261', 36686 'Conint': '\u222F', 36687 'DoubleContourIntegral': '\u222F', 36688 'ContourIntegral': '\u222E', 36689 'conint': '\u222E', 36690 'oint': '\u222E', 36691 'Copf': '\u2102', 36692 'complexes': '\u2102', 36693 'Coproduct': '\u2210', 36694 'coprod': '\u2210', 36695 'CounterClockwiseContourIntegral': '\u2233', 36696 'awconint': '\u2233', 36697 'Cross': '\u2A2F', 36698 'Cscr': '\uD835\uDC9E', 36699 'Cup': '\u22D3', 36700 'CupCap': '\u224D', 36701 'asympeq': '\u224D', 36702 'DDotrahd': '\u2911', 36703 'DJcy': '\u0402', 36704 'DScy': '\u0405', 36705 'DZcy': '\u040F', 36706 'Dagger': '\u2021', 36707 'ddagger': '\u2021', 36708 'Darr': '\u21A1', 36709 'Dashv': '\u2AE4', 36710 'DoubleLeftTee': '\u2AE4', 36711 'Dcaron': '\u010E', 36712 'Dcy': '\u0414', 36713 'Del': '\u2207', 36714 'nabla': '\u2207', 36715 'Delta': '\u0394', 36716 'Dfr': '\uD835\uDD07', 36717 'DiacriticalAcute': '\u00B4', 36718 'acute': '\u00B4', 36719 'DiacriticalDot': '\u02D9', 36720 'dot': '\u02D9', 36721 'DiacriticalDoubleAcute': '\u02DD', 36722 'dblac': '\u02DD', 36723 'DiacriticalGrave': '\u0060', 36724 'grave': '\u0060', 36725 'DiacriticalTilde': '\u02DC', 36726 'tilde': '\u02DC', 36727 'Diamond': '\u22C4', 36728 'diam': '\u22C4', 36729 'diamond': '\u22C4', 36730 'DifferentialD': '\u2146', 36731 'dd': '\u2146', 36732 'Dopf': '\uD835\uDD3B', 36733 'Dot': '\u00A8', 36734 'DoubleDot': '\u00A8', 36735 'die': '\u00A8', 36736 'uml': '\u00A8', 36737 'DotDot': '\u20DC', 36738 'DotEqual': '\u2250', 36739 'doteq': '\u2250', 36740 'esdot': '\u2250', 36741 'DoubleDownArrow': '\u21D3', 36742 'Downarrow': '\u21D3', 36743 'dArr': '\u21D3', 36744 'DoubleLeftArrow': '\u21D0', 36745 'Leftarrow': '\u21D0', 36746 'lArr': '\u21D0', 36747 'DoubleLeftRightArrow': '\u21D4', 36748 'Leftrightarrow': '\u21D4', 36749 'hArr': '\u21D4', 36750 'iff': '\u21D4', 36751 'DoubleLongLeftArrow': '\u27F8', 36752 'Longleftarrow': '\u27F8', 36753 'xlArr': '\u27F8', 36754 'DoubleLongLeftRightArrow': '\u27FA', 36755 'Longleftrightarrow': '\u27FA', 36756 'xhArr': '\u27FA', 36757 'DoubleLongRightArrow': '\u27F9', 36758 'Longrightarrow': '\u27F9', 36759 'xrArr': '\u27F9', 36760 'DoubleRightArrow': '\u21D2', 36761 'Implies': '\u21D2', 36762 'Rightarrow': '\u21D2', 36763 'rArr': '\u21D2', 36764 'DoubleRightTee': '\u22A8', 36765 'vDash': '\u22A8', 36766 'DoubleUpArrow': '\u21D1', 36767 'Uparrow': '\u21D1', 36768 'uArr': '\u21D1', 36769 'DoubleUpDownArrow': '\u21D5', 36770 'Updownarrow': '\u21D5', 36771 'vArr': '\u21D5', 36772 'DoubleVerticalBar': '\u2225', 36773 'par': '\u2225', 36774 'parallel': '\u2225', 36775 'shortparallel': '\u2225', 36776 'spar': '\u2225', 36777 'DownArrow': '\u2193', 36778 'ShortDownArrow': '\u2193', 36779 'darr': '\u2193', 36780 'downarrow': '\u2193', 36781 'DownArrowBar': '\u2913', 36782 'DownArrowUpArrow': '\u21F5', 36783 'duarr': '\u21F5', 36784 'DownBreve': '\u0311', 36785 'DownLeftRightVector': '\u2950', 36786 'DownLeftTeeVector': '\u295E', 36787 'DownLeftVector': '\u21BD', 36788 'leftharpoondown': '\u21BD', 36789 'lhard': '\u21BD', 36790 'DownLeftVectorBar': '\u2956', 36791 'DownRightTeeVector': '\u295F', 36792 'DownRightVector': '\u21C1', 36793 'rhard': '\u21C1', 36794 'rightharpoondown': '\u21C1', 36795 'DownRightVectorBar': '\u2957', 36796 'DownTee': '\u22A4', 36797 'top': '\u22A4', 36798 'DownTeeArrow': '\u21A7', 36799 'mapstodown': '\u21A7', 36800 'Dscr': '\uD835\uDC9F', 36801 'Dstrok': '\u0110', 36802 'ENG': '\u014A', 36803 'ETH': '\u00D0', 36804 'Eacute': '\u00C9', 36805 'Ecaron': '\u011A', 36806 'Ecirc': '\u00CA', 36807 'Ecy': '\u042D', 36808 'Edot': '\u0116', 36809 'Efr': '\uD835\uDD08', 36810 'Egrave': '\u00C8', 36811 'Element': '\u2208', 36812 'in': '\u2208', 36813 'isin': '\u2208', 36814 'isinv': '\u2208', 36815 'Emacr': '\u0112', 36816 'EmptySmallSquare': '\u25FB', 36817 'EmptyVerySmallSquare': '\u25AB', 36818 'Eogon': '\u0118', 36819 'Eopf': '\uD835\uDD3C', 36820 'Epsilon': '\u0395', 36821 'Equal': '\u2A75', 36822 'EqualTilde': '\u2242', 36823 'eqsim': '\u2242', 36824 'esim': '\u2242', 36825 'Equilibrium': '\u21CC', 36826 'rightleftharpoons': '\u21CC', 36827 'rlhar': '\u21CC', 36828 'Escr': '\u2130', 36829 'expectation': '\u2130', 36830 'Esim': '\u2A73', 36831 'Eta': '\u0397', 36832 'Euml': '\u00CB', 36833 'Exists': '\u2203', 36834 'exist': '\u2203', 36835 'ExponentialE': '\u2147', 36836 'ee': '\u2147', 36837 'exponentiale': '\u2147', 36838 'Fcy': '\u0424', 36839 'Ffr': '\uD835\uDD09', 36840 'FilledSmallSquare': '\u25FC', 36841 'FilledVerySmallSquare': '\u25AA', 36842 'blacksquare': '\u25AA', 36843 'squarf': '\u25AA', 36844 'squf': '\u25AA', 36845 'Fopf': '\uD835\uDD3D', 36846 'ForAll': '\u2200', 36847 'forall': '\u2200', 36848 'Fouriertrf': '\u2131', 36849 'Fscr': '\u2131', 36850 'GJcy': '\u0403', 36851 'GT': '\u003E', 36852 'gt': '\u003E', 36853 'Gamma': '\u0393', 36854 'Gammad': '\u03DC', 36855 'Gbreve': '\u011E', 36856 'Gcedil': '\u0122', 36857 'Gcirc': '\u011C', 36858 'Gcy': '\u0413', 36859 'Gdot': '\u0120', 36860 'Gfr': '\uD835\uDD0A', 36861 'Gg': '\u22D9', 36862 'ggg': '\u22D9', 36863 'Gopf': '\uD835\uDD3E', 36864 'GreaterEqual': '\u2265', 36865 'ge': '\u2265', 36866 'geq': '\u2265', 36867 'GreaterEqualLess': '\u22DB', 36868 'gel': '\u22DB', 36869 'gtreqless': '\u22DB', 36870 'GreaterFullEqual': '\u2267', 36871 'gE': '\u2267', 36872 'geqq': '\u2267', 36873 'GreaterGreater': '\u2AA2', 36874 'GreaterLess': '\u2277', 36875 'gl': '\u2277', 36876 'gtrless': '\u2277', 36877 'GreaterSlantEqual': '\u2A7E', 36878 'geqslant': '\u2A7E', 36879 'ges': '\u2A7E', 36880 'GreaterTilde': '\u2273', 36881 'gsim': '\u2273', 36882 'gtrsim': '\u2273', 36883 'Gscr': '\uD835\uDCA2', 36884 'Gt': '\u226B', 36885 'NestedGreaterGreater': '\u226B', 36886 'gg': '\u226B', 36887 'HARDcy': '\u042A', 36888 'Hacek': '\u02C7', 36889 'caron': '\u02C7', 36890 'Hat': '\u005E', 36891 'Hcirc': '\u0124', 36892 'Hfr': '\u210C', 36893 'Poincareplane': '\u210C', 36894 'HilbertSpace': '\u210B', 36895 'Hscr': '\u210B', 36896 'hamilt': '\u210B', 36897 'Hopf': '\u210D', 36898 'quaternions': '\u210D', 36899 'HorizontalLine': '\u2500', 36900 'boxh': '\u2500', 36901 'Hstrok': '\u0126', 36902 'HumpEqual': '\u224F', 36903 'bumpe': '\u224F', 36904 'bumpeq': '\u224F', 36905 'IEcy': '\u0415', 36906 'IJlig': '\u0132', 36907 'IOcy': '\u0401', 36908 'Iacute': '\u00CD', 36909 'Icirc': '\u00CE', 36910 'Icy': '\u0418', 36911 'Idot': '\u0130', 36912 'Ifr': '\u2111', 36913 'Im': '\u2111', 36914 'image': '\u2111', 36915 'imagpart': '\u2111', 36916 'Igrave': '\u00CC', 36917 'Imacr': '\u012A', 36918 'ImaginaryI': '\u2148', 36919 'ii': '\u2148', 36920 'Int': '\u222C', 36921 'Integral': '\u222B', 36922 'int': '\u222B', 36923 'Intersection': '\u22C2', 36924 'bigcap': '\u22C2', 36925 'xcap': '\u22C2', 36926 'InvisibleComma': '\u2063', 36927 'ic': '\u2063', 36928 'InvisibleTimes': '\u2062', 36929 'it': '\u2062', 36930 'Iogon': '\u012E', 36931 'Iopf': '\uD835\uDD40', 36932 'Iota': '\u0399', 36933 'Iscr': '\u2110', 36934 'imagline': '\u2110', 36935 'Itilde': '\u0128', 36936 'Iukcy': '\u0406', 36937 'Iuml': '\u00CF', 36938 'Jcirc': '\u0134', 36939 'Jcy': '\u0419', 36940 'Jfr': '\uD835\uDD0D', 36941 'Jopf': '\uD835\uDD41', 36942 'Jscr': '\uD835\uDCA5', 36943 'Jsercy': '\u0408', 36944 'Jukcy': '\u0404', 36945 'KHcy': '\u0425', 36946 'KJcy': '\u040C', 36947 'Kappa': '\u039A', 36948 'Kcedil': '\u0136', 36949 'Kcy': '\u041A', 36950 'Kfr': '\uD835\uDD0E', 36951 'Kopf': '\uD835\uDD42', 36952 'Kscr': '\uD835\uDCA6', 36953 'LJcy': '\u0409', 36954 'LT': '\u003C', 36955 'lt': '\u003C', 36956 'Lacute': '\u0139', 36957 'Lambda': '\u039B', 36958 'Lang': '\u27EA', 36959 'Laplacetrf': '\u2112', 36960 'Lscr': '\u2112', 36961 'lagran': '\u2112', 36962 'Larr': '\u219E', 36963 'twoheadleftarrow': '\u219E', 36964 'Lcaron': '\u013D', 36965 'Lcedil': '\u013B', 36966 'Lcy': '\u041B', 36967 'LeftAngleBracket': '\u27E8', 36968 'lang': '\u27E8', 36969 'langle': '\u27E8', 36970 'LeftArrow': '\u2190', 36971 'ShortLeftArrow': '\u2190', 36972 'larr': '\u2190', 36973 'leftarrow': '\u2190', 36974 'slarr': '\u2190', 36975 'LeftArrowBar': '\u21E4', 36976 'larrb': '\u21E4', 36977 'LeftArrowRightArrow': '\u21C6', 36978 'leftrightarrows': '\u21C6', 36979 'lrarr': '\u21C6', 36980 'LeftCeiling': '\u2308', 36981 'lceil': '\u2308', 36982 'LeftDoubleBracket': '\u27E6', 36983 'lobrk': '\u27E6', 36984 'LeftDownTeeVector': '\u2961', 36985 'LeftDownVector': '\u21C3', 36986 'dharl': '\u21C3', 36987 'downharpoonleft': '\u21C3', 36988 'LeftDownVectorBar': '\u2959', 36989 'LeftFloor': '\u230A', 36990 'lfloor': '\u230A', 36991 'LeftRightArrow': '\u2194', 36992 'harr': '\u2194', 36993 'leftrightarrow': '\u2194', 36994 'LeftRightVector': '\u294E', 36995 'LeftTee': '\u22A3', 36996 'dashv': '\u22A3', 36997 'LeftTeeArrow': '\u21A4', 36998 'mapstoleft': '\u21A4', 36999 'LeftTeeVector': '\u295A', 37000 'LeftTriangle': '\u22B2', 37001 'vartriangleleft': '\u22B2', 37002 'vltri': '\u22B2', 37003 'LeftTriangleBar': '\u29CF', 37004 'LeftTriangleEqual': '\u22B4', 37005 'ltrie': '\u22B4', 37006 'trianglelefteq': '\u22B4', 37007 'LeftUpDownVector': '\u2951', 37008 'LeftUpTeeVector': '\u2960', 37009 'LeftUpVector': '\u21BF', 37010 'uharl': '\u21BF', 37011 'upharpoonleft': '\u21BF', 37012 'LeftUpVectorBar': '\u2958', 37013 'LeftVector': '\u21BC', 37014 'leftharpoonup': '\u21BC', 37015 'lharu': '\u21BC', 37016 'LeftVectorBar': '\u2952', 37017 'LessEqualGreater': '\u22DA', 37018 'leg': '\u22DA', 37019 'lesseqgtr': '\u22DA', 37020 'LessFullEqual': '\u2266', 37021 'lE': '\u2266', 37022 'leqq': '\u2266', 37023 'LessGreater': '\u2276', 37024 'lessgtr': '\u2276', 37025 'lg': '\u2276', 37026 'LessLess': '\u2AA1', 37027 'LessSlantEqual': '\u2A7D', 37028 'leqslant': '\u2A7D', 37029 'les': '\u2A7D', 37030 'LessTilde': '\u2272', 37031 'lesssim': '\u2272', 37032 'lsim': '\u2272', 37033 'Lfr': '\uD835\uDD0F', 37034 'Ll': '\u22D8', 37035 'Lleftarrow': '\u21DA', 37036 'lAarr': '\u21DA', 37037 'Lmidot': '\u013F', 37038 'LongLeftArrow': '\u27F5', 37039 'longleftarrow': '\u27F5', 37040 'xlarr': '\u27F5', 37041 'LongLeftRightArrow': '\u27F7', 37042 'longleftrightarrow': '\u27F7', 37043 'xharr': '\u27F7', 37044 'LongRightArrow': '\u27F6', 37045 'longrightarrow': '\u27F6', 37046 'xrarr': '\u27F6', 37047 'Lopf': '\uD835\uDD43', 37048 'LowerLeftArrow': '\u2199', 37049 'swarr': '\u2199', 37050 'swarrow': '\u2199', 37051 'LowerRightArrow': '\u2198', 37052 'searr': '\u2198', 37053 'searrow': '\u2198', 37054 'Lsh': '\u21B0', 37055 'lsh': '\u21B0', 37056 'Lstrok': '\u0141', 37057 'Lt': '\u226A', 37058 'NestedLessLess': '\u226A', 37059 'll': '\u226A', 37060 'Map': '\u2905', 37061 'Mcy': '\u041C', 37062 'MediumSpace': '\u205F', 37063 'Mellintrf': '\u2133', 37064 'Mscr': '\u2133', 37065 'phmmat': '\u2133', 37066 'Mfr': '\uD835\uDD10', 37067 'MinusPlus': '\u2213', 37068 'mnplus': '\u2213', 37069 'mp': '\u2213', 37070 'Mopf': '\uD835\uDD44', 37071 'Mu': '\u039C', 37072 'NJcy': '\u040A', 37073 'Nacute': '\u0143', 37074 'Ncaron': '\u0147', 37075 'Ncedil': '\u0145', 37076 'Ncy': '\u041D', 37077 'NegativeMediumSpace': '\u200B', 37078 'NegativeThickSpace': '\u200B', 37079 'NegativeThinSpace': '\u200B', 37080 'NegativeVeryThinSpace': '\u200B', 37081 'ZeroWidthSpace': '\u200B', 37082 'NewLine': '\u000A', 37083 'Nfr': '\uD835\uDD11', 37084 'NoBreak': '\u2060', 37085 'NonBreakingSpace': '\u00A0', 37086 'nbsp': '\u00A0', 37087 'Nopf': '\u2115', 37088 'naturals': '\u2115', 37089 'Not': '\u2AEC', 37090 'NotCongruent': '\u2262', 37091 'nequiv': '\u2262', 37092 'NotCupCap': '\u226D', 37093 'NotDoubleVerticalBar': '\u2226', 37094 'npar': '\u2226', 37095 'nparallel': '\u2226', 37096 'nshortparallel': '\u2226', 37097 'nspar': '\u2226', 37098 'NotElement': '\u2209', 37099 'notin': '\u2209', 37100 'notinva': '\u2209', 37101 'NotEqual': '\u2260', 37102 'ne': '\u2260', 37103 'NotEqualTilde': '\u2242\u0338', 37104 'nesim': '\u2242\u0338', 37105 'NotExists': '\u2204', 37106 'nexist': '\u2204', 37107 'nexists': '\u2204', 37108 'NotGreater': '\u226F', 37109 'ngt': '\u226F', 37110 'ngtr': '\u226F', 37111 'NotGreaterEqual': '\u2271', 37112 'nge': '\u2271', 37113 'ngeq': '\u2271', 37114 'NotGreaterFullEqual': '\u2267\u0338', 37115 'ngE': '\u2267\u0338', 37116 'ngeqq': '\u2267\u0338', 37117 'NotGreaterGreater': '\u226B\u0338', 37118 'nGtv': '\u226B\u0338', 37119 'NotGreaterLess': '\u2279', 37120 'ntgl': '\u2279', 37121 'NotGreaterSlantEqual': '\u2A7E\u0338', 37122 'ngeqslant': '\u2A7E\u0338', 37123 'nges': '\u2A7E\u0338', 37124 'NotGreaterTilde': '\u2275', 37125 'ngsim': '\u2275', 37126 'NotHumpDownHump': '\u224E\u0338', 37127 'nbump': '\u224E\u0338', 37128 'NotHumpEqual': '\u224F\u0338', 37129 'nbumpe': '\u224F\u0338', 37130 'NotLeftTriangle': '\u22EA', 37131 'nltri': '\u22EA', 37132 'ntriangleleft': '\u22EA', 37133 'NotLeftTriangleBar': '\u29CF\u0338', 37134 'NotLeftTriangleEqual': '\u22EC',
37135 'nltrie': '\u22EC', 37136 'ntrianglelefteq': '\u22EC', 37137 'NotLess': '\u226E', 37138 'nless': '\u226E', 37139 'nlt': '\u226E', 37140 'NotLessEqual': '\u2270', 37141 'nle': '\u2270', 37142 'nleq': '\u2270', 37143 'NotLessGreater': '\u2278', 37144 'ntlg': '\u2278', 37145 'NotLessLess': '\u226A\u0338', 37146 'nLtv': '\u226A\u0338', 37147 'NotLessSlantEqual': '\u2A7D\u0338', 37148 'nleqslant': '\u2A7D\u0338', 37149 'nles': '\u2A7D\u0338', 37150 'NotLessTilde': '\u2274', 37151 'nlsim': '\u2274', 37152 'NotNestedGreaterGreater': '\u2AA2\u0338', 37153 'NotNestedLessLess': '\u2AA1\u0338', 37154 'NotPrecedes': '\u2280', 37155 'npr': '\u2280', 37156 'nprec': '\u2280', 37157 'NotPrecedesEqual': '\u2AAF\u0338', 37158 'npre': '\u2AAF\u0338', 37159 'npreceq': '\u2AAF\u0338', 37160 'NotPrecedesSlantEqual': '\u22E0', 37161 'nprcue': '\u22E0', 37162 'NotReverseElement': '\u220C', 37163 'notni': '\u220C', 37164 'notniva': '\u220C', 37165 'NotRightTriangle': '\u22EB', 37166 'nrtri': '\u22EB', 37167 'ntriangleright': '\u22EB', 37168 'NotRightTriangleBar': '\u29D0\u0338', 37169 'NotRightTriangleEqual': '\u22ED', 37170 'nrtrie': '\u22ED', 37171 'ntrianglerighteq': '\u22ED', 37172 'NotSquareSubset': '\u228F\u0338', 37173 'NotSquareSubsetEqual': '\u22E2', 37174 'nsqsube': '\u22E2', 37175 'NotSquareSuperset': '\u2290\u0338', 37176 'NotSquareSupersetEqual': '\u22E3', 37177 'nsqsupe': '\u22E3', 37178 'NotSubset': '\u2282\u20D2', 37179 'nsubset': '\u2282\u20D2', 37180 'vnsub': '\u2282\u20D2', 37181 'NotSubsetEqual': '\u2288', 37182 'nsube': '\u2288', 37183 'nsubseteq': '\u2288', 37184 'NotSucceeds': '\u2281', 37185 'nsc': '\u2281', 37186 'nsucc': '\u2281', 37187 'NotSucceedsEqual': '\u2AB0\u0338', 37188 'nsce': '\u2AB0\u0338', 37189 'nsucceq': '\u2AB0\u0338', 37190 'NotSucceedsSlantEqual': '\u22E1', 37191 'nsccue': '\u22E1', 37192 'NotSucceedsTilde': '\u227F\u0338', 37193 'NotSuperset': '\u2283\u20D2', 37194 'nsupset': '\u2283\u20D2', 37195 'vnsup': '\u2283\u20D2', 37196 'NotSupersetEqual': '\u2289', 37197 'nsupe': '\u2289', 37198 'nsupseteq': '\u2289', 37199 'NotTilde': '\u2241', 37200 'nsim': '\u2241', 37201 'NotTildeEqual': '\u2244', 37202 'nsime': '\u2244', 37203 'nsimeq': '\u2244', 37204 'NotTildeFullEqual': '\u2247', 37205 'ncong': '\u2247', 37206 'NotTildeTilde': '\u2249', 37207 'nap': '\u2249', 37208 'napprox': '\u2249', 37209 'NotVerticalBar': '\u2224', 37210 'nmid': '\u2224', 37211 'nshortmid': '\u2224', 37212 'nsmid': '\u2224', 37213 'Nscr': '\uD835\uDCA9', 37214 'Ntilde': '\u00D1', 37215 'Nu': '\u039D', 37216 'OElig': '\u0152', 37217 'Oacute': '\u00D3', 37218 'Ocirc': '\u00D4', 37219 'Ocy': '\u041E', 37220 'Odblac': '\u0150', 37221 'Ofr': '\uD835\uDD12', 37222 'Ograve': '\u00D2', 37223 'Omacr': '\u014C', 37224 'Omega': '\u03A9', 37225 'ohm': '\u03A9', 37226 'Omicron': '\u039F', 37227 'Oopf': '\uD835\uDD46', 37228 'OpenCurlyDoubleQuote': '\u201C', 37229 'ldquo': '\u201C', 37230 'OpenCurlyQuote': '\u2018', 37231 'lsquo': '\u2018', 37232 'Or': '\u2A54', 37233 'Oscr': '\uD835\uDCAA', 37234 'Oslash': '\u00D8', 37235 'Otilde': '\u00D5', 37236 'Otimes': '\u2A37', 37237 'Ouml': '\u00D6', 37238 'OverBar': '\u203E', 37239 'oline': '\u203E', 37240 'OverBrace': '\u23DE', 37241 'OverBracket': '\u23B4', 37242 'tbrk': '\u23B4', 37243 'OverParenthesis': '\u23DC', 37244 'PartialD': '\u2202', 37245 'part': '\u2202', 37246 'Pcy': '\u041F', 37247 'Pfr': '\uD835\uDD13', 37248 'Phi': '\u03A6', 37249 'Pi': '\u03A0', 37250 'PlusMinus': '\u00B1', 37251 'plusmn': '\u00B1', 37252 'pm': '\u00B1', 37253 'Popf': '\u2119', 37254 'primes': '\u2119', 37255 'Pr': '\u2ABB', 37256 'Precedes': '\u227A', 37257 'pr': '\u227A', 37258 'prec': '\u227A', 37259 'PrecedesEqual': '\u2AAF', 37260 'pre': '\u2AAF', 37261 'preceq': '\u2AAF', 37262 'PrecedesSlantEqual': '\u227C', 37263 'prcue': '\u227C', 37264 'preccurlyeq': '\u227C', 37265 'PrecedesTilde': '\u227E', 37266 'precsim': '\u227E', 37267 'prsim': '\u227E', 37268 'Prime': '\u2033', 37269 'Product': '\u220F', 37270 'prod': '\u220F', 37271 'Proportional': '\u221D', 37272 'prop': '\u221D', 37273 'propto': '\u221D', 37274 'varpropto': '\u221D', 37275 'vprop': '\u221D', 37276 'Pscr': '\uD835\uDCAB', 37277 'Psi': '\u03A8', 37278 'QUOT': '\u0022', 37279 'quot': '\u0022', 37280 'Qfr': '\uD835\uDD14', 37281 'Qopf': '\u211A', 37282 'rationals': '\u211A', 37283 'Qscr': '\uD835\uDCAC', 37284 'RBarr': '\u2910', 37285 'drbkarow': '\u2910', 37286 'REG': '\u00AE', 37287 'circledR': '\u00AE', 37288 'reg': '\u00AE', 37289 'Racute': '\u0154', 37290 'Rang': '\u27EB', 37291 'Rarr': '\u21A0', 37292 'twoheadrightarrow': '\u21A0', 37293 'Rarrtl': '\u2916', 37294 'Rcaron': '\u0158', 37295 'Rcedil': '\u0156', 37296 'Rcy': '\u0420', 37297 'Re': '\u211C', 37298 'Rfr': '\u211C', 37299 'real': '\u211C', 37300 'realpart': '\u211C', 37301 'ReverseElement': '\u220B', 37302 'SuchThat': '\u220B', 37303 'ni': '\u220B', 37304 'niv': '\u220B', 37305 'ReverseEquilibrium': '\u21CB', 37306 'leftrightharpoons': '\u21CB', 37307 'lrhar': '\u21CB', 37308 'ReverseUpEquilibrium': '\u296F', 37309 'duhar': '\u296F', 37310 'Rho': '\u03A1', 37311 'RightAngleBracket': '\u27E9', 37312 'rang': '\u27E9', 37313 'rangle': '\u27E9', 37314 'RightArrow': '\u2192', 37315 'ShortRightArrow': '\u2192', 37316 'rarr': '\u2192', 37317 'rightarrow': '\u2192', 37318 'srarr': '\u2192', 37319 'RightArrowBar': '\u21E5', 37320 'rarrb': '\u21E5', 37321 'RightArrowLeftArrow': '\u21C4', 37322 'rightleftarrows': '\u21C4', 37323 'rlarr': '\u21C4', 37324 'RightCeiling': '\u2309',
37325 'rceil': '\u2309', 37326 'RightDoubleBracket': '\u27E7', 37327 'robrk': '\u27E7', 37328 'RightDownTeeVector': '\u295D', 37329 'RightDownVector': '\u21C2', 37330 'dharr': '\u21C2', 37331 'downharpoonright': '\u21C2', 37332 'RightDownVectorBar': '\u2955', 37333 'RightFloor': '\u230B', 37334 'rfloor': '\u230B', 37335 'RightTee': '\u22A2', 37336 'vdash': '\u22A2', 37337 'RightTeeArrow': '\u21A6', 37338 'map': '\u21A6', 37339 'mapsto': '\u21A6', 37340 'RightTeeVector': '\u295B', 37341 'RightTriangle': '\u22B3', 37342 'vartriangleright': '\u22B3', 37343 'vrtri': '\u22B3', 37344 'RightTriangleBar': '\u29D0', 37345 'RightTriangleEqual': '\u22B5', 37346 'rtrie': '\u22B5', 37347 'trianglerighteq': '\u22B5', 37348 'RightUpDownVector': '\u294F', 37349 'RightUpTeeVector': '\u295C', 37350 'RightUpVector': '\u21BE', 37351 'uharr': '\u21BE', 37352 'upharpoonright': '\u21BE', 37353 'RightUpVectorBar': '\u2954', 37354 'RightVector': '\u21C0', 37355 'rharu': '\u21C0', 37356 'rightharpoonup': '\u21C0', 37357 'RightVectorBar': '\u2953', 37358 'Ropf': '\u211D', 37359 'reals': '\u211D', 37360 'RoundImplies': '\u2970', 37361 'Rrightarrow': '\u21DB', 37362 'rAarr': '\u21DB', 37363 'Rscr': '\u211B', 37364 'realine': '\u211B', 37365 'Rsh': '\u21B1', 37366 'rsh': '\u21B1', 37367 'RuleDelayed': '\u29F4', 37368 'SHCHcy': '\u0429', 37369 'SHcy': '\u0428', 37370 'SOFTcy': '\u042C', 37371 'Sacute': '\u015A', 37372 'Sc': '\u2ABC', 37373 'Scaron': '\u0160', 37374 'Scedil': '\u015E', 37375 'Scirc': '\u015C', 37376 'Scy': '\u0421', 37377 'Sfr': '\uD835\uDD16', 37378 'ShortUpArrow': '\u2191', 37379 'UpArrow': '\u2191', 37380 'uarr': '\u2191', 37381 'uparrow': '\u2191', 37382 'Sigma': '\u03A3', 37383 'SmallCircle': '\u2218', 37384 'compfn': '\u2218', 37385 'Sopf': '\uD835\uDD4A', 37386 'Sqrt': '\u221A', 37387 'radic': '\u221A', 37388 'Square': '\u25A1', 37389 'squ': '\u25A1', 37390 'square': '\u25A1', 37391 'SquareIntersection': '\u2293', 37392 'sqcap': '\u2293', 37393 'SquareSubset': '\u228F', 37394 'sqsub': '\u228F', 37395 'sqsubset': '\u228F', 37396 'SquareSubsetEqual': '\u2291', 37397 'sqsube': '\u2291', 37398 'sqsubseteq': '\u2291', 37399 'SquareSuperset': '\u2290', 37400 'sqsup': '\u2290', 37401 'sqsupset': '\u2290', 37402 'SquareSupersetEqual': '\u2292', 37403 'sqsupe': '\u2292', 37404 'sqsupseteq': '\u2292', 37405 'SquareUnion': '\u2294', 37406 'sqcup': '\u2294', 37407 'Sscr': '\uD835\uDCAE', 37408 'Star': '\u22C6', 37409 'sstarf': '\u22C6', 37410 'Sub': '\u22D0', 37411 'Subset': '\u22D0', 37412 'SubsetEqual': '\u2286', 37413 'sube': '\u2286', 37414 'subseteq': '\u2286', 37415 'Succeeds': '\u227B', 37416 'sc': '\u227B', 37417 'succ': '\u227B', 37418 'SucceedsEqual': '\u2AB0', 37419 'sce': '\u2AB0', 37420 'succeq': '\u2AB0', 37421 'SucceedsSlantEqual': '\u227D', 37422 'sccue': '\u227D', 37423 'succcurlyeq': '\u227D', 37424 'SucceedsTilde': '\u227F', 37425 'scsim': '\u227F', 37426 'succsim': '\u227F', 37427 'Sum': '\u2211', 37428 'sum': '\u2211', 37429 'Sup': '\u22D1', 37430 'Supset': '\u22D1', 37431 'Superset': '\u2283', 37432 'sup': '\u2283', 37433 'supset': '\u2283', 37434 'SupersetEqual': '\u2287', 37435 'supe': '\u2287', 37436 'supseteq': '\u2287', 37437 'THORN': '\u00DE', 37438 'TRADE': '\u2122', 37439 'trade': '\u2122', 37440 'TSHcy': '\u040B', 37441 'TScy': '\u0426', 37442 'Tab': '\u0009', 37443 'Tau': '\u03A4', 37444 'Tcaron': '\u0164', 37445 'Tcedil': '\u0162', 37446 'Tcy': '\u0422', 37447 'Tfr': '\uD835\uDD17', 37448 'Therefore': '\u2234', 37449 'there4': '\u2234', 37450 'therefore': '\u2234', 37451 'Theta': '\u0398', 37452 'ThickSpace': '\u205F\u200A', 37453 'ThinSpace': '\u2009', 37454 'thinsp': '\u2009', 37455 'Tilde': '\u223C', 37456 'sim': '\u223C', 37457 'thicksim': '\u223C', 37458 'thksim': '\u223C', 37459 'TildeEqual': '\u2243', 37460 'sime': '\u2243', 37461 'simeq': '\u2243', 37462 'TildeFullEqual': '\u2245', 37463 'cong': '\u2245', 37464 'TildeTilde': '\u2248', 37465 'ap': '\u2248', 37466 'approx': '\u2248', 37467 'asymp': '\u2248', 37468 'thickapprox': '\u2248', 37469 'thkap': '\u2248', 37470 'Topf': '\uD835\uDD4B', 37471 'TripleDot': '\u20DB', 37472 'tdot': '\u20DB', 37473 'Tscr': '\uD835\uDCAF', 37474 'Tstrok': '\u0166', 37475 'Uacute': '\u00DA', 37476 'Uarr': '\u219F', 37477 'Uarrocir': '\u2949', 37478 'Ubrcy': '\u040E', 37479 'Ubreve': '\u016C', 37480 'Ucirc': '\u00DB', 37481 'Ucy': '\u0423', 37482 'Udblac': '\u0170', 37483 'Ufr': '\uD835\uDD18', 37484 'Ugrave': '\u00D9', 37485 'Umacr': '\u016A', 37486 'UnderBar': '\u005F', 37487 'lowbar': '\u005F', 37488 'UnderBrace': '\u23DF', 37489 'UnderBracket': '\u23B5', 37490 'bbrk': '\u23B5', 37491 'UnderParenthesis': '\u23DD', 37492 'Union': '\u22C3', 37493 'bigcup': '\u22C3', 37494 'xcup': '\u22C3', 37495 'UnionPlus': '\u228E', 37496 'uplus': '\u228E', 37497 'Uogon': '\u0172', 37498 'Uopf': '\uD835\uDD4C', 37499 'UpArrowBar': '\u2912', 37500 'UpArrowDownArrow': '\u21C5', 37501 'udarr': '\u21C5', 37502 'UpDownArrow': '\u2195', 37503 'updownarrow': '\u2195', 37504 'varr': '\u2195', 37505 'UpEquilibrium': '\u296E', 37506 'udhar': '\u296E', 37507 'UpTee': '\u22A5', 37508 'bot': '\u22A5', 37509 'bottom': '\u22A5', 37510 'perp': '\u22A5', 37511 'UpTeeArrow': '\u21A5', 37512 'mapstoup': '\u21A5', 37513 'UpperLeftArrow': '\u2196', 37514 'nwarr': '\u2196', 37515 'nwarrow': '\u2196', 37516 'UpperRightArrow': '\u2197', 37517 'nearr': '\u2197', 37518 'nearrow': '\u2197', 37519 'Upsi': '\u03D2', 37520 'upsih': '\u03D2', 37521 'Upsilon': '\u03A5', 37522 'Uring': '\u016E', 37523 'Uscr': '\uD835\uDCB0', 37524 'Utilde': '\u0168', 37525 'Uuml': '\u00DC',
37526 'VDash': '\u22AB', 37527 'Vbar': '\u2AEB', 37528 'Vcy': '\u0412', 37529 'Vdash': '\u22A9', 37530 'Vdashl': '\u2AE6', 37531 'Vee': '\u22C1', 37532 'bigvee': '\u22C1', 37533 'xvee': '\u22C1', 37534 'Verbar': '\u2016', 37535 'Vert': '\u2016', 37536 'VerticalBar': '\u2223', 37537 'mid': '\u2223', 37538 'shortmid': '\u2223', 37539 'smid': '\u2223', 37540 'VerticalLine': '\u007C', 37541 'verbar': '\u007C', 37542 'vert': '\u007C', 37543 'VerticalSeparator': '\u2758', 37544 'VerticalTilde': '\u2240', 37545 'wr': '\u2240', 37546 'wreath': '\u2240', 37547 'VeryThinSpace': '\u200A', 37548 'hairsp': '\u200A', 37549 'Vfr': '\uD835\uDD19', 37550 'Vopf': '\uD835\uDD4D', 37551 'Vscr': '\uD835\uDCB1', 37552 'Vvdash': '\u22AA', 37553 'Wcirc': '\u0174', 37554 'Wedge': '\u22C0', 37555 'bigwedge': '\u22C0', 37556 'xwedge': '\u22C0', 37557 'Wfr': '\uD835\uDD1A', 37558 'Wopf': '\uD835\uDD4E', 37559 'Wscr': '\uD835\uDCB2', 37560 'Xfr': '\uD835\uDD1B', 37561 'Xi': '\u039E', 37562 'Xopf': '\uD835\uDD4F', 37563 'Xscr': '\uD835\uDCB3', 37564 'YAcy': '\u042F', 37565 'YIcy': '\u0407', 37566 'YUcy': '\u042E', 37567 'Yacute': '\u00DD', 37568 'Ycirc': '\u0176', 37569 'Ycy': '\u042B', 37570 'Yfr': '\uD835\uDD1C', 37571 'Yopf': '\uD835\uDD50', 37572 'Yscr': '\uD835\uDCB4', 37573 'Yuml': '\u0178', 37574 'ZHcy': '\u0416', 37575 'Zacute': '\u0179', 37576 'Zcaron': '\u017D', 37577 'Zcy': '\u0417', 37578 'Zdot': '\u017B', 37579 'Zeta': '\u0396', 37580 'Zfr': '\u2128', 37581 'zeetrf': '\u2128', 37582 'Zopf': '\u2124', 37583 'integers': '\u2124', 37584 'Zscr': '\uD835\uDCB5', 37585 'aacute': '\u00E1', 37586 'abreve': '\u0103', 37587 'ac': '\u223E', 37588 'mstpos': '\u223E', 37589 'acE': '\u223E\u0333', 37590 'acd': '\u223F', 37591 'acirc': '\u00E2', 37592 'acy': '\u0430', 37593 'aelig': '\u00E6', 37594 'afr': '\uD835\uDD1E', 37595 'agrave': '\u00E0', 37596 'alefsym': '\u2135', 37597 'aleph': '\u2135', 37598 'alpha': '\u03B1', 37599 'amacr': '\u0101', 37600 'amalg': '\u2A3F', 37601 'and': '\u2227', 37602 'wedge': '\u2227', 37603 'andand': '\u2A55', 37604 'andd': '\u2A5C', 37605 'andslope': '\u2A58', 37606 'andv': '\u2A5A', 37607 'ang': '\u2220', 37608 'angle': '\u2220', 37609 'ange': '\u29A4', 37610 'angmsd': '\u2221', 37611 'measuredangle': '\u2221', 37612 'angmsdaa': '\u29A8', 37613 'angmsdab': '\u29A9', 37614 'angmsdac': '\u29AA', 37615 'angmsdad': '\u29AB', 37616 'angmsdae': '\u29AC', 37617 'angmsdaf': '\u29AD', 37618 'angmsdag': '\u29AE', 37619 'angmsdah': '\u29AF', 37620 'angrt': '\u221F', 37621 'angrtvb': '\u22BE', 37622 'angrtvbd': '\u299D', 37623 'angsph': '\u2222', 37624 'angzarr': '\u237C', 37625 'aogon': '\u0105', 37626 'aopf': '\uD835\uDD52', 37627 'apE': '\u2A70', 37628 'apacir': '\u2A6F', 37629 'ape': '\u224A', 37630 'approxeq': '\u224A', 37631 'apid': '\u224B', 37632 'apos': '\u0027', 37633 'aring': '\u00E5', 37634 'ascr': '\uD835\uDCB6', 37635 'ast': '\u002A', 37636 'midast': '\u002A', 37637 'atilde': '\u00E3', 37638 'auml': '\u00E4', 37639 'awint': '\u2A11', 37640 'bNot': '\u2AED', 37641 'backcong': '\u224C', 37642 'bcong': '\u224C', 37643 'backepsilon': '\u03F6', 37644 'bepsi': '\u03F6', 37645 'backprime': '\u2035', 37646 'bprime': '\u2035', 37647 'backsim': '\u223D', 37648 'bsim': '\u223D', 37649 'backsimeq': '\u22CD', 37650 'bsime': '\u22CD', 37651 'barvee': '\u22BD', 37652 'barwed': '\u2305', 37653 'barwedge': '\u2305', 37654 'bbrktbrk': '\u23B6', 37655 'bcy': '\u0431', 37656 'bdquo': '\u201E', 37657 'ldquor': '\u201E', 37658 'bemptyv': '\u29B0', 37659 'beta': '\u03B2', 37660 'beth': '\u2136', 37661 'between': '\u226C', 37662 'twixt': '\u226C', 37663 'bfr': '\uD835\uDD1F', 37664 'bigcirc': '\u25EF', 37665 'xcirc': '\u25EF', 37666 'bigodot': '\u2A00', 37667 'xodot': '\u2A00', 37668 'bigoplus': '\u2A01', 37669 'xoplus': '\u2A01', 37670 'bigotimes': '\u2A02', 37671 'xotime': '\u2A02', 37672 'bigsqcup': '\u2A06', 37673 'xsqcup': '\u2A06', 37674 'bigstar': '\u2605', 37675 'starf': '\u2605', 37676 'bigtriangledown': '\u25BD', 37677 'xdtri': '\u25BD', 37678 'bigtriangleup': '\u25B3', 37679 'xutri': '\u25B3', 37680 'biguplus': '\u2A04', 37681 'xuplus': '\u2A04', 37682 'bkarow': '\u290D', 37683 'rbarr': '\u290D', 37684 'blacklozenge': '\u29EB', 37685 'lozf': '\u29EB', 37686 'blacktriangle': '\u25B4', 37687 'utrif': '\u25B4', 37688 'blacktriangledown': '\u25BE', 37689 'dtrif': '\u25BE', 37690 'blacktriangleleft': '\u25C2', 37691 'ltrif': '\u25C2', 37692 'blacktriangleright': '\u25B8', 37693 'rtrif': '\u25B8', 37694 'blank': '\u2423', 37695 'blk12': '\u2592', 37696 'blk14': '\u2591', 37697 'blk34': '\u2593', 37698 'block': '\u2588', 37699 'bne': '\u003D\u20E5', 37700 'bnequiv': '\u2261\u20E5', 37701 'bnot': '\u2310', 37702 'bopf': '\uD835\uDD53', 37703 'bowtie': '\u22C8', 37704 'boxDL': '\u2557', 37705 'boxDR': '\u2554', 37706 'boxDl': '\u2556', 37707 'boxDr': '\u2553', 37708 'boxH': '\u2550', 37709 'boxHD': '\u2566', 37710 'boxHU': '\u2569', 37711 'boxHd': '\u2564', 37712 'boxHu': '\u2567', 37713 'boxUL': '\u255D', 37714 'boxUR': '\u255A', 37715 'boxUl': '\u255C', 37716 'boxUr': '\u2559', 37717 'boxV': '\u2551', 37718 'boxVH': '\u256C', 37719 'boxVL': '\u2563', 37720 'boxVR': '\u2560', 37721 'boxVh': '\u256B', 37722 'boxVl': '\u2562', 37723 'boxVr': '\u255F', 37724 'boxbox': '\u29C9', 37725 'boxdL': '\u2555', 37726 'boxdR': '\u2552', 37727 'boxdl': '\u2510', 37728 'boxdr': '\u250C', 37729 'boxhD': '\u2565', 37730 'boxhU': '\u2568', 37731 'boxhd': '\u252C', 37732 'boxhu': '\u2534', 37733 'boxminus': '\u229F', 37734 'minusb': '\u229F', 37735 'boxplus': '\u229E', 37736 'plusb': '\u229E', 37737 'boxtimes': '\u22A0', 37738 'timesb': '\u22A0', 37739 'boxuL': '\u255B', 37740 'boxuR': '\u2558', 37741 'boxul': '\u2518', 37742 'boxur': '\u2514', 37743 'boxv': '\u2502', 37744 'boxvH': '\u256A', 37745 'boxvL': '\u2561', 37746 'boxvR': '\u255E', 37747 'boxvh': '\u253C', 37748 'boxvl': '\u2524', 37749 'boxvr': '\u251C', 37750 'brvbar': '\u00A6', 37751 'bscr': '\uD835\uDCB7', 37752 'bsemi': '\u204F', 37753 'bsol': '\u005C', 37754 'bsolb': '\u29C5', 37755 'bsolhsub': '\u27C8', 37756 'bull': '\u2022', 37757 'bullet': '\u2022', 37758 'bumpE': '\u2AAE', 37759 'cacute': '\u0107', 37760 'cap': '\u2229', 37761 'capand': '\u2A44', 37762 'capbrcup': '\u2A49', 37763 'capcap': '\u2A4B', 37764 'capcup': '\u2A47', 37765 'capdot': '\u2A40', 37766 'caps': '\u2229\uFE00', 37767 'caret': '\u2041', 37768 'ccaps': '\u2A4D', 37769 'ccaron': '\u010D', 37770 'ccedil': '\u00E7', 37771 'ccirc': '\u0109', 37772 'ccups': '\u2A4C', 37773 'ccupssm': '\u2A50', 37774 'cdot': '\u010B', 37775 'cemptyv': '\u29B2', 37776 'cent': '\u00A2', 37777 'cfr': '\uD835\uDD20', 37778 'chcy': '\u0447', 37779 'check': '\u2713', 37780 'checkmark': '\u2713', 37781 'chi': '\u03C7', 37782 'cir': '\u25CB', 37783 'cirE': '\u29C3', 37784 'circ': '\u02C6', 37785 'circeq': '\u2257', 37786 'cire': '\u2257', 37787 'circlearrowleft': '\u21BA', 37788 'olarr': '\u21BA', 37789 'circlearrowright': '\u21BB', 37790 'orarr': '\u21BB', 37791 'circledS': '\u24C8', 37792 'oS': '\u24C8', 37793 'circledast': '\u229B', 37794 'oast': '\u229B', 37795 'circledcirc': '\u229A', 37796 'ocir': '\u229A', 37797 'circleddash': '\u229D', 37798 'odash': '\u229D', 37799 'cirfnint': '\u2A10', 37800 'cirmid': '\u2AEF', 37801 'cirscir': '\u29C2', 37802 'clubs': '\u2663', 37803 'clubsuit': '\u2663', 37804 'colon': '\u003A', 37805 'comma': '\u002C', 37806 'commat': '\u0040', 37807 'comp': '\u2201', 37808 'complement': '\u2201', 37809 'congdot': '\u2A6D', 37810 'copf': '\uD835\uDD54', 37811 'copysr': '\u2117', 37812 'crarr': '\u21B5', 37813 'cross': '\u2717', 37814 'cscr': '\uD835\uDCB8', 37815 'csub': '\u2ACF', 37816 'csube': '\u2AD1', 37817 'csup': '\u2AD0', 37818 'csupe': '\u2AD2', 37819 'ctdot': '\u22EF', 37820 'cudarrl': '\u2938', 37821 'cudarrr': '\u2935', 37822 'cuepr': '\u22DE', 37823 'curlyeqprec': '\u22DE', 37824 'cuesc': '\u22DF', 37825 'curlyeqsucc': '\u22DF', 37826 'cularr': '\u21B6', 37827 'curvearrowleft': '\u21B6', 37828 'cularrp': '\u293D', 37829 'cup': '\u222A', 37830 'cupbrcap': '\u2A48', 37831 'cupcap': '\u2A46', 37832 'cupcup': '\u2A4A', 37833 'cupdot': '\u228D', 37834 'cupor': '\u2A45', 37835 'cups': '\u222A\uFE00', 37836 'curarr': '\u21B7', 37837 'curvearrowright': '\u21B7', 37838 'curarrm': '\u293C', 37839 'curlyvee': '\u22CE', 37840 'cuvee': '\u22CE', 37841 'curlywedge': '\u22CF', 37842 'cuwed': '\u22CF', 37843 'curren': '\u00A4', 37844 'cwint': '\u2231', 37845 'cylcty': '\u232D', 37846 'dHar': '\u2965', 37847 'dagger': '\u2020', 37848 'daleth': '\u2138', 37849 'dash': '\u2010', 37850 'hyphen': '\u2010', 37851 'dbkarow': '\u290F', 37852 'rBarr': '\u290F', 37853 'dcaron': '\u010F', 37854 'dcy': '\u0434', 37855 'ddarr': '\u21CA', 37856 'downdownarrows': '\u21CA', 37857 'ddotseq': '\u2A77', 37858 'eDDot': '\u2A77', 37859 'deg': '\u00B0', 37860 'delta': '\u03B4', 37861 'demptyv': '\u29B1', 37862 'dfisht': '\u297F', 37863 'dfr': '\uD835\uDD21', 37864 'diamondsuit': '\u2666', 37865 'diams': '\u2666', 37866 'digamma': '\u03DD', 37867 'gammad': '\u03DD', 37868 'disin': '\u22F2', 37869 'div': '\u00F7', 37870 'divide': '\u00F7', 37871 'divideontimes': '\u22C7', 37872 'divonx': '\u22C7', 37873 'djcy': '\u0452', 37874 'dlcorn': '\u231E', 37875 'llcorner': '\u231E', 37876 'dlcrop': '\u230D', 37877 'dollar': '\u0024', 37878 'dopf': '\uD835\uDD55', 37879 'doteqdot': '\u2251', 37880 'eDot': '\u2251', 37881 'dotminus': '\u2238', 37882 'minusd': '\u2238', 37883 'dotplus': '\u2214', 37884 'plusdo': '\u2214', 37885 'dotsquare': '\u22A1', 37886 'sdotb': '\u22A1', 37887 'drcorn': '\u231F', 37888 'lrcorner': '\u231F', 37889 'drcrop': '\u230C', 37890 'dscr': '\uD835\uDCB9', 37891 'dscy': '\u0455', 37892 'dsol': '\u29F6', 37893 'dstrok': '\u0111', 37894 'dtdot': '\u22F1', 37895 'dtri': '\u25BF', 37896 'triangledown': '\u25BF', 37897 'dwangle': '\u29A6', 37898 'dzcy': '\u045F', 37899 'dzigrarr': '\u27FF', 37900 'eacute': '\u00E9', 37901 'easter': '\u2A6E', 37902 'ecaron': '\u011B', 37903 'ecir': '\u2256', 37904 'eqcirc': '\u2256', 37905 'ecirc': '\u00EA', 37906 'ecolon': '\u2255', 37907 'eqcolon': '\u2255', 37908 'ecy': '\u044D', 37909 'edot': '\u0117', 37910 'efDot': '\u2252', 37911 'fallingdotseq': '\u2252', 37912 'efr': '\uD835\uDD22', 37913 'eg': '\u2A9A', 37914 'egrave': '\u00E8', 37915 'egs': '\u2A96', 37916 'eqslantgtr': '\u2A96', 37917 'egsdot': '\u2A98', 37918 'el': '\u2A99', 37919 'elinters': '\u23E7', 37920 'ell': '\u2113', 37921 'els': '\u2A95', 37922 'eqslantless': '\u2A95', 37923 'elsdot': '\u2A97', 37924 'emacr': '\u0113', 37925 'empty': '\u2205', 37926 'emptyset': '\u2205', 37927 'emptyv': '\u2205', 37928 'varnothing': '\u2205', 37929 'emsp13': '\u2004', 37930 'emsp14': '\u2005', 37931 'emsp': '\u2003', 37932 'eng': '\u014B', 37933 'ensp': '\u2002', 37934 'eogon': '\u0119', 37935 'eopf': '\uD835\uDD56', 37936 'epar': '\u22D5', 37937 'eparsl': '\u29E3', 37938 'eplus': '\u2A71', 37939 'epsi': '\u03B5', 37940 'epsilon': '\u03B5', 37941 'epsiv': '\u03F5', 37942 'straightepsilon': '\u03F5', 37943 'varepsilon': '\u03F5', 37944 'equals': '\u003D', 37945 'equest': '\u225F', 37946 'questeq': '\u225F', 37947 'equivDD': '\u2A78', 37948 'eqvparsl': '\u29E5', 37949 'erDot': '\u2253', 37950 'risingdotseq': '\u2253', 37951 'erarr': '\u2971', 37952 'escr': '\u212F', 37953 'eta': '\u03B7', 37954 'eth': '\u00F0', 37955 'euml': '\u00EB', 37956 'euro': '\u20AC', 37957 'excl': '\u0021', 37958 'fcy': '\u0444', 37959 'female': '\u2640', 37960 'ffilig': '\uFB03', 37961 'fflig': '\uFB00', 37962 'ffllig': '\uFB04', 37963 'ffr': '\uD835\uDD23', 37964 'filig': '\uFB01', 37965 'fjlig': '\u0066\u006A', 37966 'flat': '\u266D', 37967 'fllig': '\uFB02', 37968 'fltns': '\u25B1', 37969 'fnof': '\u0192', 37970 'fopf': '\uD835\uDD57', 37971 'fork': '\u22D4', 37972 'pitchfork': '\u22D4', 37973 'forkv': '\u2AD9', 37974 'fpartint': '\u2A0D', 37975 'frac12': '\u00BD', 37976 'half': '\u00BD', 37977 'frac13': '\u2153', 37978 'frac14': '\u00BC', 37979 'frac15': '\u2155', 37980 'frac16': '\u2159', 37981 'frac18': '\u215B', 37982 'frac23': '\u2154', 37983 'frac25': '\u2156', 37984 'frac34': '\u00BE', 37985 'frac35': '\u2157', 37986 'frac38': '\u215C', 37987 'frac45': '\u2158', 37988 'frac56': '\u215A',
37989 'frac58': '\u215D', 37990 'frac78': '\u215E', 37991 'frasl': '\u2044', 37992 'frown': '\u2322', 37993 'sfrown': '\u2322', 37994 'fscr': '\uD835\uDCBB', 37995 'gEl': '\u2A8C', 37996 'gtreqqless': '\u2A8C', 37997 'gacute': '\u01F5', 37998 'gamma': '\u03B3', 37999 'gap': '\u2A86', 38000 'gtrapprox': '\u2A86', 38001 'gbreve': '\u011F', 38002 'gcirc': '\u011D', 38003 'gcy': '\u0433', 38004 'gdot': '\u0121', 38005 'gescc': '\u2AA9', 38006 'gesdot': '\u2A80', 38007 'gesdoto': '\u2A82', 38008 'gesdotol': '\u2A84', 38009 'gesl': '\u22DB\uFE00', 38010 'gesles': '\u2A94', 38011 'gfr': '\uD835\uDD24', 38012 'gimel': '\u2137', 38013 'gjcy': '\u0453', 38014 'glE': '\u2A92', 38015 'gla': '\u2AA5', 38016 'glj': '\u2AA4', 38017 'gnE': '\u2269', 38018 'gneqq': '\u2269', 38019 'gnap': '\u2A8A', 38020 'gnapprox': '\u2A8A', 38021 'gne': '\u2A88', 38022 'gneq': '\u2A88', 38023 'gnsim': '\u22E7', 38024 'gopf': '\uD835\uDD58', 38025 'gscr': '\u210A', 38026 'gsime': '\u2A8E', 38027 'gsiml': '\u2A90', 38028 'gtcc': '\u2AA7', 38029 'gtcir': '\u2A7A', 38030 'gtdot': '\u22D7', 38031 'gtrdot': '\u22D7', 38032 'gtlPar': '\u2995', 38033 'gtquest': '\u2A7C', 38034 'gtrarr': '\u2978', 38035 'gvertneqq': '\u2269\uFE00', 38036 'gvnE': '\u2269\uFE00', 38037 'hardcy': '\u044A', 38038 'harrcir': '\u2948', 38039 'harrw': '\u21AD', 38040 'leftrightsquigarrow': '\u21AD', 38041 'hbar': '\u210F', 38042 'hslash': '\u210F', 38043 'planck': '\u210F', 38044 'plankv': '\u210F', 38045 'hcirc': '\u0125', 38046 'hearts': '\u2665', 38047 'heartsuit': '\u2665', 38048 'hellip': '\u2026', 38049 'mldr': '\u2026', 38050 'hercon': '\u22B9', 38051 'hfr': '\uD835\uDD25', 38052 'hksearow': '\u2925', 38053 'searhk': '\u2925', 38054 'hkswarow': '\u2926', 38055 'swarhk': '\u2926', 38056 'hoarr': '\u21FF', 38057 'homtht': '\u223B', 38058 'hookleftarrow': '\u21A9', 38059 'larrhk': '\u21A9', 38060 'hookrightarrow': '\u21AA', 38061 'rarrhk': '\u21AA', 38062 'hopf': '\uD835\uDD59', 38063 'horbar': '\u2015', 38064 'hscr': '\uD835\uDCBD', 38065 'hstrok': '\u0127', 38066 'hybull': '\u2043', 38067 'iacute': '\u00ED', 38068 'icirc': '\u00EE', 38069 'icy': '\u0438', 38070 'iecy': '\u0435', 38071 'iexcl': '\u00A1', 38072 'ifr': '\uD835\uDD26', 38073 'igrave': '\u00EC', 38074 'iiiint': '\u2A0C', 38075 'qint': '\u2A0C', 38076 'iiint': '\u222D', 38077 'tint': '\u222D', 38078 'iinfin': '\u29DC', 38079 'iiota': '\u2129', 38080 'ijlig': '\u0133', 38081 'imacr': '\u012B', 38082 'imath': '\u0131', 38083 'inodot': '\u0131', 38084 'imof': '\u22B7', 38085 'imped': '\u01B5', 38086 'incare': '\u2105', 38087 'infin': '\u221E', 38088 'infintie': '\u29DD', 38089 'intcal': '\u22BA', 38090 'intercal': '\u22BA', 38091 'intlarhk': '\u2A17', 38092 'intprod': '\u2A3C', 38093 'iprod': '\u2A3C', 38094 'iocy': '\u0451', 38095 'iogon': '\u012F', 38096 'iopf': '\uD835\uDD5A', 38097 'iota': '\u03B9', 38098 'iquest': '\u00BF', 38099 'iscr': '\uD835\uDCBE', 38100 'isinE': '\u22F9', 38101 'isindot': '\u22F5', 38102 'isins': '\u22F4', 38103 'isinsv': '\u22F3', 38104 'itilde': '\u0129', 38105 'iukcy': '\u0456', 38106 'iuml': '\u00EF', 38107 'jcirc': '\u0135', 38108 'jcy': '\u0439', 38109 'jfr': '\uD835\uDD27', 38110 'jmath': '\u0237', 38111 'jopf': '\uD835\uDD5B', 38112 'jscr': '\uD835\uDCBF', 38113 'jsercy': '\u0458', 38114 'jukcy': '\u0454', 38115 'kappa': '\u03BA', 38116 'kappav': '\u03F0', 38117 'varkappa': '\u03F0', 38118 'kcedil': '\u0137', 38119 'kcy': '\u043A', 38120 'kfr': '\uD835\uDD28', 38121 'kgreen': '\u0138', 38122 'khcy': '\u0445', 38123 'kjcy': '\u045C', 38124 'kopf': '\uD835\uDD5C', 38125 'kscr': '\uD835\uDCC0', 38126 'lAtail': '\u291B', 38127 'lBarr': '\u290E', 38128 'lEg': '\u2A8B', 38129 'lesseqqgtr': '\u2A8B', 38130 'lHar': '\u2962', 38131 'lacute': '\u013A', 38132 'laemptyv': '\u29B4', 38133 'lambda': '\u03BB', 38134 'langd': '\u2991', 38135 'lap': '\u2A85', 38136 'lessapprox': '\u2A85', 38137 'laquo': '\u00AB', 38138 'larrbfs': '\u291F', 38139 'larrfs': '\u291D', 38140 'larrlp': '\u21AB', 38141 'looparrowleft': '\u21AB', 38142 'larrpl': '\u2939', 38143 'larrsim': '\u2973', 38144 'larrtl': '\u21A2', 38145 'leftarrowtail': '\u21A2', 38146 'lat': '\u2AAB', 38147 'latail': '\u2919', 38148 'late': '\u2AAD', 38149 'lates': '\u2AAD\uFE00', 38150 'lbarr': '\u290C', 38151 'lbbrk': '\u2772', 38152 'lbrace': '\u007B', 38153 'lcub': '\u007B', 38154 'lbrack': '\u005B', 38155 'lsqb': '\u005B', 38156 'lbrke': '\u298B', 38157 'lbrksld': '\u298F', 38158 'lbrkslu': '\u298D', 38159 'lcaron': '\u013E', 38160 'lcedil': '\u013C', 38161 'lcy': '\u043B', 38162 'ldca': '\u2936', 38163 'ldrdhar': '\u2967', 38164 'ldrushar': '\u294B', 38165 'ldsh': '\u21B2', 38166 'le': '\u2264', 38167 'leq': '\u2264', 38168 'leftleftarrows': '\u21C7', 38169 'llarr': '\u21C7', 38170 'leftthreetimes': '\u22CB', 38171 'lthree': '\u22CB', 38172 'lescc': '\u2AA8', 38173 'lesdot': '\u2A7F', 38174 'lesdoto': '\u2A81', 38175 'lesdotor': '\u2A83', 38176 'lesg': '\u22DA\uFE00', 38177 'lesges': '\u2A93', 38178 'lessdot': '\u22D6', 38179 'ltdot': '\u22D6', 38180 'lfisht': '\u297C', 38181 'lfr': '\uD835\uDD29', 38182 'lgE': '\u2A91', 38183 'lharul': '\u296A', 38184 'lhblk': '\u2584', 38185 'ljcy': '\u0459', 38186 'llhard': '\u296B', 38187 'lltri': '\u25FA', 38188 'lmidot': '\u0140', 38189 'lmoust': '\u23B0', 38190 'lmoustache': '\u23B0', 38191 'lnE': '\u2268', 38192 'lneqq': '\u2268', 38193 'lnap': '\u2A89', 38194 'lnapprox': '\u2A89', 38195 'lne': '\u2A87', 38196 'lneq': '\u2A87', 38197 'lnsim': '\u22E6', 38198 'loang': '\u27EC', 38199 'loarr': '\u21FD', 38200 'longmapsto': '\u27FC', 38201 'xmap': '\u27FC', 38202 'looparrowright': '\u21AC', 38203 'rarrlp': '\u21AC', 38204 'lopar': '\u2985', 38205 'lopf': '\uD835\uDD5D', 38206 'loplus': '\u2A2D', 38207 'lotimes': '\u2A34', 38208 'lowast': '\u2217', 38209 'loz': '\u25CA', 38210 'lozenge': '\u25CA', 38211 'lpar': '\u0028', 38212 'lparlt': '\u2993', 38213 'lrhard': '\u296D', 38214 'lrm': '\u200E', 38215 'lrtri': '\u22BF', 38216 'lsaquo': '\u2039', 38217 'lscr': '\uD835\uDCC1', 38218 'lsime': '\u2A8D', 38219 'lsimg': '\u2A8F', 38220 'lsquor': '\u201A', 38221 'sbquo': '\u201A', 38222 'lstrok': '\u0142', 38223 'ltcc': '\u2AA6', 38224 'ltcir': '\u2A79', 38225 'ltimes': '\u22C9', 38226 'ltlarr': '\u2976', 38227 'ltquest': '\u2A7B', 38228 'ltrPar': '\u2996', 38229 'ltri': '\u25C3', 38230 'triangleleft': '\u25C3', 38231 'lurdshar': '\u294A', 38232 'luruhar': '\u2966', 38233 'lvertneqq': '\u2268\uFE00', 38234 'lvnE': '\u2268\uFE00', 38235 'mDDot': '\u223A', 38236 'macr': '\u00AF', 38237 'strns': '\u00AF', 38238 'male': '\u2642', 38239 'malt': '\u2720', 38240 'maltese': '\u2720', 38241 'marker': '\u25AE', 38242 'mcomma': '\u2A29', 38243 'mcy': '\u043C', 38244 'mdash': '\u2014', 38245 'mfr': '\uD835\uDD2A', 38246 'mho': '\u2127', 38247 'micro': '\u00B5', 38248 'midcir': '\u2AF0', 38249 'minus': '\u2212', 38250 'minusdu': '\u2A2A', 38251 'mlcp': '\u2ADB', 38252 'models': '\u22A7', 38253 'mopf': '\uD835\uDD5E', 38254 'mscr': '\uD835\uDCC2', 38255 'mu': '\u03BC', 38256 'multimap': '\u22B8', 38257 'mumap': '\u22B8', 38258 'nGg': '\u22D9\u0338', 38259 'nGt': '\u226B\u20D2', 38260 'nLeftarrow': '\u21CD', 38261 'nlArr': '\u21CD', 38262 'nLeftrightarrow': '\u21CE', 38263 'nhArr': '\u21CE', 38264 'nLl': '\u22D8\u0338', 38265 'nLt': '\u226A\u20D2', 38266 'nRightarrow': '\u21CF', 38267 'nrArr': '\u21CF', 38268 'nVDash': '\u22AF', 38269 'nVdash': '\u22AE', 38270 'nacute': '\u0144', 38271 'nang': '\u2220\u20D2', 38272 'napE': '\u2A70\u0338', 38273 'napid': '\u224B\u0338', 38274 'napos': '\u0149', 38275 'natur': '\u266E', 38276 'natural': '\u266E', 38277 'ncap': '\u2A43', 38278 'ncaron': '\u0148', 38279 'ncedil': '\u0146', 38280 'ncongdot': '\u2A6D\u0338', 38281 'ncup': '\u2A42', 38282 'ncy': '\u043D', 38283 'ndash': '\u2013', 38284 'neArr': '\u21D7', 38285 'nearhk': '\u2924', 38286 'nedot': '\u2250\u0338', 38287 'nesear': '\u2928', 38288 'toea': '\u2928', 38289 'nfr': '\uD835\uDD2B', 38290 'nharr': '\u21AE', 38291 'nleftrightarrow': '\u21AE', 38292 'nhpar': '\u2AF2', 38293 'nis': '\u22FC', 38294 'nisd': '\u22FA', 38295 'njcy': '\u045A', 38296 'nlE': '\u2266\u0338', 38297 'nleqq': '\u2266\u0338', 38298 'nlarr': '\u219A', 38299 'nleftarrow': '\u219A', 38300 'nldr': '\u2025', 38301 'nopf': '\uD835\uDD5F', 38302 'not': '\u00AC', 38303 'notinE': '\u22F9\u0338', 38304 'notindot': '\u22F5\u0338', 38305 'notinvb': '\u22F7', 38306 'notinvc': '\u22F6', 38307 'notnivb': '\u22FE', 38308 'notnivc': '\u22FD', 38309 'nparsl': '\u2AFD\u20E5',
38310 'npart': '\u2202\u0338', 38311 'npolint': '\u2A14', 38312 'nrarr': '\u219B', 38313 'nrightarrow': '\u219B', 38314 'nrarrc': '\u2933\u0338', 38315 'nrarrw': '\u219D\u0338', 38316 'nscr': '\uD835\uDCC3', 38317 'nsub': '\u2284', 38318 'nsubE': '\u2AC5\u0338', 38319 'nsubseteqq': '\u2AC5\u0338', 38320 'nsup': '\u2285', 38321 'nsupE': '\u2AC6\u0338', 38322 'nsupseteqq': '\u2AC6\u0338', 38323 'ntilde': '\u00F1', 38324 'nu': '\u03BD', 38325 'num': '\u0023', 38326 'numero': '\u2116', 38327 'numsp': '\u2007', 38328 'nvDash': '\u22AD', 38329 'nvHarr': '\u2904', 38330 'nvap': '\u224D\u20D2', 38331 'nvdash': '\u22AC', 38332 'nvge': '\u2265\u20D2', 38333 'nvgt': '\u003E\u20D2', 38334 'nvinfin': '\u29DE', 38335 'nvlArr': '\u2902', 38336 'nvle': '\u2264\u20D2', 38337 'nvlt': '\u003C\u20D2', 38338 'nvltrie': '\u22B4\u20D2', 38339 'nvrArr': '\u2903', 38340 'nvrtrie': '\u22B5\u20D2', 38341 'nvsim': '\u223C\u20D2', 38342 'nwArr': '\u21D6', 38343 'nwarhk': '\u2923', 38344 'nwnear': '\u2927', 38345 'oacute': '\u00F3', 38346 'ocirc': '\u00F4', 38347 'ocy': '\u043E', 38348 'odblac': '\u0151', 38349 'odiv': '\u2A38', 38350 'odsold': '\u29BC', 38351 'oelig': '\u0153', 38352 'ofcir': '\u29BF', 38353 'ofr': '\uD835\uDD2C', 38354 'ogon': '\u02DB', 38355 'ograve': '\u00F2', 38356 'ogt': '\u29C1', 38357 'ohbar': '\u29B5', 38358 'olcir': '\u29BE', 38359 'olcross': '\u29BB', 38360 'olt': '\u29C0', 38361 'omacr': '\u014D', 38362 'omega': '\u03C9', 38363 'omicron': '\u03BF', 38364 'omid': '\u29B6', 38365 'oopf': '\uD835\uDD60', 38366 'opar': '\u29B7', 38367 'operp': '\u29B9', 38368 'or': '\u2228', 38369 'vee': '\u2228', 38370 'ord': '\u2A5D', 38371 'order': '\u2134', 38372 'orderof': '\u2134', 38373 'oscr': '\u2134', 38374 'ordf': '\u00AA', 38375 'ordm': '\u00BA', 38376 'origof': '\u22B6', 38377 'oror': '\u2A56', 38378 'orslope': '\u2A57', 38379 'orv': '\u2A5B', 38380 'oslash': '\u00F8', 38381 'osol': '\u2298', 38382 'otilde': '\u00F5', 38383 'otimesas': '\u2A36', 38384 'ouml': '\u00F6', 38385 'ovbar': '\u233D', 38386 'para': '\u00B6', 38387 'parsim': '\u2AF3', 38388 'parsl': '\u2AFD', 38389 'pcy': '\u043F', 38390 'percnt': '\u0025', 38391 'period': '\u002E', 38392 'permil': '\u2030', 38393 'pertenk': '\u2031', 38394 'pfr': '\uD835\uDD2D', 38395 'phi': '\u03C6', 38396 'phiv': '\u03D5', 38397 'straightphi': '\u03D5', 38398 'varphi': '\u03D5', 38399 'phone': '\u260E', 38400 'pi': '\u03C0', 38401 'piv': '\u03D6', 38402 'varpi': '\u03D6', 38403 'planckh': '\u210E', 38404 'plus': '\u002B', 38405 'plusacir': '\u2A23', 38406 'pluscir': '\u2A22', 38407 'plusdu': '\u2A25', 38408 'pluse': '\u2A72', 38409 'plussim': '\u2A26', 38410 'plustwo': '\u2A27', 38411 'pointint': '\u2A15', 38412 'popf': '\uD835\uDD61', 38413 'pound': '\u00A3', 38414 'prE': '\u2AB3', 38415 'prap': '\u2AB7', 38416 'precapprox': '\u2AB7', 38417 'precnapprox': '\u2AB9', 38418 'prnap': '\u2AB9', 38419 'precneqq': '\u2AB5', 38420 'prnE': '\u2AB5', 38421 'precnsim': '\u22E8', 38422 'prnsim': '\u22E8', 38423 'prime': '\u2032', 38424 'profalar': '\u232E', 38425 'profline': '\u2312', 38426 'profsurf': '\u2313', 38427 'prurel': '\u22B0', 38428 'pscr': '\uD835\uDCC5', 38429 'psi': '\u03C8', 38430 'puncsp': '\u2008', 38431 'qfr': '\uD835\uDD2E', 38432 'qopf': '\uD835\uDD62', 38433 'qprime': '\u2057', 38434 'qscr': '\uD835\uDCC6', 38435 'quatint': '\u2A16', 38436 'quest': '\u003F', 38437 'rAtail': '\u291C', 38438 'rHar': '\u2964', 38439 'race': '\u223D\u0331', 38440 'racute': '\u0155', 38441 'raemptyv': '\u29B3', 38442 'rangd': '\u2992', 38443 'range': '\u29A5', 38444 'raquo': '\u00BB', 38445 'rarrap': '\u2975', 38446 'rarrbfs': '\u2920', 38447 'rarrc': '\u2933', 38448 'rarrfs': '\u291E', 38449 'rarrpl': '\u2945', 38450 'rarrsim': '\u2974', 38451 'rarrtl': '\u21A3', 38452 'rightarrowtail': '\u21A3', 38453 'rarrw': '\u219D', 38454 'rightsquigarrow': '\u219D', 38455 'ratail': '\u291A', 38456 'ratio': '\u2236', 38457 'rbbrk': '\u2773', 38458 'rbrace': '\u007D', 38459 'rcub': '\u007D', 38460 'rbrack': '\u005D', 38461 'rsqb': '\u005D', 38462 'rbrke': '\u298C', 38463 'rbrksld': '\u298E', 38464 'rbrkslu': '\u2990', 38465 'rcaron': '\u0159', 38466 'rcedil': '\u0157', 38467 'rcy': '\u0440', 38468 'rdca': '\u2937', 38469 'rdldhar': '\u2969', 38470 'rdsh': '\u21B3', 38471 'rect': '\u25AD', 38472 'rfisht': '\u297D', 38473 'rfr': '\uD835\uDD2F', 38474 'rharul': '\u296C', 38475 'rho': '\u03C1', 38476 'rhov': '\u03F1', 38477 'varrho': '\u03F1', 38478 'rightrightarrows': '\u21C9', 38479 'rrarr': '\u21C9', 38480 'rightthreetimes': '\u22CC', 38481 'rthree': '\u22CC', 38482 'ring': '\u02DA', 38483 'rlm': '\u200F', 38484 'rmoust': '\u23B1', 38485 'rmoustache': '\u23B1', 38486 'rnmid': '\u2AEE', 38487 'roang': '\u27ED', 38488 'roarr': '\u21FE', 38489 'ropar': '\u2986', 38490 'ropf': '\uD835\uDD63', 38491 'roplus': '\u2A2E', 38492 'rotimes': '\u2A35', 38493 'rpar': '\u0029', 38494 'rpargt': '\u2994', 38495 'rppolint': '\u2A12', 38496 'rsaquo': '\u203A', 38497 'rscr': '\uD835\uDCC7', 38498 'rtimes': '\u22CA', 38499 'rtri': '\u25B9', 38500 'triangleright': '\u25B9', 38501 'rtriltri': '\u29CE', 38502 'ruluhar': '\u2968', 38503 'rx': '\u211E', 38504 'sacute': '\u015B', 38505 'scE': '\u2AB4', 38506 'scap': '\u2AB8', 38507 'succapprox': '\u2AB8', 38508 'scaron': '\u0161', 38509 'scedil': '\u015F', 38510 'scirc': '\u015D', 38511 'scnE': '\u2AB6', 38512 'succneqq': '\u2AB6', 38513 'scnap': '\u2ABA', 38514 'succnapprox': '\u2ABA', 38515 'scnsim': '\u22E9', 38516 'succnsim': '\u22E9', 38517 'scpolint': '\u2A13', 38518 'scy': '\u0441', 38519 'sdot': '\u22C5', 38520 'sdote': '\u2A66', 38521 'seArr': '\u21D8', 38522 'sect': '\u00A7', 38523 'semi': '\u003B', 38524 'seswar': '\u2929', 38525 'tosa': '\u2929', 38526 'sext': '\u2736', 38527 'sfr': '\uD835\uDD30', 38528 'sharp': '\u266F', 38529 'shchcy': '\u0449', 38530 'shcy': '\u0448', 38531 'shy': '\u00AD', 38532 'sigma': '\u03C3', 38533 'sigmaf': '\u03C2', 38534 'sigmav': '\u03C2', 38535 'varsigma': '\u03C2', 38536 'simdot': '\u2A6A', 38537 'simg': '\u2A9E', 38538 'simgE': '\u2AA0', 38539 'siml': '\u2A9D', 38540 'simlE': '\u2A9F', 38541 'simne': '\u2246', 38542 'simplus': '\u2A24', 38543 'simrarr': '\u2972', 38544 'smashp': '\u2A33', 38545 'smeparsl': '\u29E4', 38546 'smile': '\u2323', 38547 'ssmile': '\u2323', 38548 'smt': '\u2AAA', 38549 'smte': '\u2AAC', 38550 'smtes': '\u2AAC\uFE00', 38551 'softcy': '\u044C', 38552 'sol': '\u002F', 38553 'solb': '\u29C4', 38554 'solbar': '\u233F', 38555 'sopf': '\uD835\uDD64', 38556 'spades': '\u2660', 38557 'spadesuit': '\u2660', 38558 'sqcaps': '\u2293\uFE00', 38559 'sqcups': '\u2294\uFE00', 38560 'sscr': '\uD835\uDCC8', 38561 'star': '\u2606', 38562 'sub': '\u2282', 38563 'subset': '\u2282', 38564 'subE': '\u2AC5', 38565 'subseteqq': '\u2AC5', 38566 'subdot': '\u2ABD', 38567 'subedot': '\u2AC3', 38568 'submult': '\u2AC1', 38569 'subnE': '\u2ACB', 38570 'subsetneqq': '\u2ACB', 38571 'subne': '\u228A', 38572 'subsetneq': '\u228A', 38573 'subplus': '\u2ABF', 38574 'subrarr': '\u2979', 38575 'subsim': '\u2AC7', 38576 'subsub': '\u2AD5', 38577 'subsup': '\u2AD3', 38578 'sung': '\u266A', 38579 'sup1': '\u00B9', 38580 'sup2': '\u00B2', 38581 'sup3': '\u00B3', 38582 'supE': '\u2AC6', 38583 'supseteqq': '\u2AC6', 38584 'supdot': '\u2ABE', 38585 'supdsub': '\u2AD8', 38586 'supedot': '\u2AC4', 38587 'suphsol': '\u27C9', 38588 'suphsub': '\u2AD7', 38589 'suplarr': '\u297B',
38590 'supmult': '\u2AC2', 38591 'supnE': '\u2ACC', 38592 'supsetneqq': '\u2ACC', 38593 'supne': '\u228B', 38594 'supsetneq': '\u228B', 38595 'supplus': '\u2AC0', 38596 'supsim': '\u2AC8', 38597 'supsub': '\u2AD4', 38598 'supsup': '\u2AD6', 38599 'swArr': '\u21D9', 38600 'swnwar': '\u292A', 38601 'szlig': '\u00DF', 38602 'target': '\u2316', 38603 'tau': '\u03C4', 38604 'tcaron': '\u0165', 38605 'tcedil': '\u0163', 38606 'tcy': '\u0442', 38607 'telrec': '\u2315', 38608 'tfr': '\uD835\uDD31', 38609 'theta': '\u03B8', 38610 'thetasym': '\u03D1', 38611 'thetav': '\u03D1', 38612 'vartheta': '\u03D1', 38613 'thorn': '\u00FE', 38614 'times': '\u00D7', 38615 'timesbar': '\u2A31', 38616 'timesd': '\u2A30', 38617 'topbot': '\u2336', 38618 'topcir': '\u2AF1', 38619 'topf': '\uD835\uDD65', 38620 'topfork': '\u2ADA', 38621 'tprime': '\u2034', 38622 'triangle': '\u25B5', 38623 'utri': '\u25B5', 38624 'triangleq': '\u225C', 38625 'trie': '\u225C', 38626 'tridot': '\u25EC', 38627 'triminus': '\u2A3A', 38628 'triplus': '\u2A39', 38629 'trisb': '\u29CD', 38630 'tritime': '\u2A3B', 38631 'trpezium': '\u23E2', 38632 'tscr': '\uD835\uDCC9', 38633 'tscy': '\u0446', 38634 'tshcy': '\u045B', 38635 'tstrok': '\u0167', 38636 'uHar': '\u2963', 38637 'uacute': '\u00FA', 38638 'ubrcy': '\u045E', 38639 'ubreve': '\u016D', 38640 'ucirc': '\u00FB', 38641 'ucy': '\u0443', 38642 'udblac': '\u0171', 38643 'ufisht': '\u297E', 38644 'ufr': '\uD835\uDD32', 38645 'ugrave': '\u00F9', 38646 'uhblk': '\u2580', 38647 'ulcorn': '\u231C', 38648 'ulcorner': '\u231C', 38649 'ulcrop': '\u230F', 38650 'ultri': '\u25F8', 38651 'umacr': '\u016B', 38652 'uogon': '\u0173', 38653 'uopf': '\uD835\uDD66', 38654 'upsi': '\u03C5', 38655 'upsilon': '\u03C5', 38656 'upuparrows': '\u21C8', 38657 'uuarr': '\u21C8', 38658 'urcorn': '\u231D', 38659 'urcorner': '\u231D', 38660 'urcrop': '\u230E', 38661 'uring': '\u016F', 38662 'urtri': '\u25F9', 38663 'uscr': '\uD835\uDCCA', 38664 'utdot': '\u22F0', 38665 'utilde': '\u0169', 38666 'uuml': '\u00FC', 38667 'uwangle': '\u29A7', 38668 'vBar': '\u2AE8', 38669 'vBarv': '\u2AE9', 38670 'vangrt': '\u299C', 38671 'varsubsetneq': '\u228A\uFE00', 38672 'vsubne': '\u228A\uFE00', 38673 'varsubsetneqq': '\u2ACB\uFE00', 38674 'vsubnE': '\u2ACB\uFE00', 38675 'varsupsetneq': '\u228B\uFE00', 38676 'vsupne': '\u228B\uFE00', 38677 'varsupsetneqq': '\u2ACC\uFE00', 38678 'vsupnE': '\u2ACC\uFE00', 38679 'vcy': '\u0432', 38680 'veebar': '\u22BB', 38681 'veeeq': '\u225A', 38682 'vellip': '\u22EE', 38683 'vfr': '\uD835\uDD33', 38684 'vopf': '\uD835\uDD67', 38685 'vscr': '\uD835\uDCCB', 38686 'vzigzag': '\u299A', 38687 'wcirc': '\u0175', 38688 'wedbar': '\u2A5F', 38689 'wedgeq': '\u2259', 38690 'weierp': '\u2118', 38691 'wp': '\u2118', 38692 'wfr': '\uD835\uDD34', 38693 'wopf': '\uD835\uDD68', 38694 'wscr': '\uD835\uDCCC', 38695 'xfr': '\uD835\uDD35', 38696 'xi': '\u03BE', 38697 'xnis': '\u22FB', 38698 'xopf': '\uD835\uDD69', 38699 'xscr': '\uD835\uDCCD', 38700 'yacute': '\u00FD', 38701 'yacy': '\u044F', 38702 'ycirc': '\u0177', 38703 'ycy': '\u044B', 38704 'yen': '\u00A5', 38705 'yfr': '\uD835\uDD36', 38706 'yicy': '\u0457', 38707 'yopf': '\uD835\uDD6A', 38708 'yscr': '\uD835\uDCCE', 38709 'yucy': '\u044E', 38710 'yuml': '\u00FF', 38711 'zacute': '\u017A', 38712 'zcaron': '\u017E', 38713 'zcy': '\u0437', 38714 'zdot': '\u017C', 38715 'zeta': '\u03B6', 38716 'zfr': '\uD835\uDD37', 38717 'zhcy': '\u0436', 38718 'zigrarr': '\u21DD', 38719 'zopf': '\uD835\uDD6B', 38720 'zscr': '\uD835\uDCCF', 38721 'zwj': '\u200D', 38722 'zwnj': '\u200C' 38723}; // The &ngsp; pseudo-entity is denoting a space. see: 38724// https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart 38725 38726const NGSP_UNICODE = '\uE500'; 38727NAMED_ENTITIES['ngsp'] = NGSP_UNICODE; 38728/** 38729 * @license 38730 * Copyright Google LLC All Rights Reserved. 38731 * 38732 * Use of this source code is governed by an MIT-style license that can be 38733 * found in the LICENSE file at https://angular.io/license 38734 */ 38735 38736class TokenError extends ParseError { 38737 constructor(errorMsg, tokenType, span) { 38738 super(span, errorMsg); 38739 this.tokenType = tokenType; 38740 } 38741 38742} 38743 38744class TokenizeResult { 38745 constructor(tokens, errors, nonNormalizedIcuExpressions) { 38746 this.tokens = tokens; 38747 this.errors = errors; 38748 this.nonNormalizedIcuExpressions = nonNormalizedIcuExpressions; 38749 } 38750 38751} 38752 38753function tokenize(source, url, getTagDefinition, options = {}) { 38754 const tokenizer = new _Tokenizer(new ParseSourceFile(source, url), getTagDefinition, options); 38755 tokenizer.tokenize(); 38756 return new TokenizeResult(mergeTextTokens(tokenizer.tokens), tokenizer.errors, tokenizer.nonNormalizedIcuExpressions); 38757} 38758 38759const _CR_OR_CRLF_REGEXP = /\r\n?/g; 38760 38761function _unexpectedCharacterErrorMsg(charCode) { 38762 const char = charCode === $EOF ? 'EOF' : String.fromCharCode(charCode); 38763 return `Unexpected character "${char}"`; 38764} 38765 38766function _unknownEntityErrorMsg(entitySrc) { 38767 return `Unknown entity "${entitySrc}" - use the "&#<decimal>;" or "&#x<hex>;" syntax`; 38768} 38769 38770function _unparsableEntityErrorMsg(type, entityStr) { 38771 return `Unable to parse entity "${entityStr}" - ${type} character reference entities must end with ";"`; 38772} 38773 38774var CharacterReferenceType; 38775 38776(function (CharacterReferenceType) { 38777 CharacterReferenceType["HEX"] = "hexadecimal"; 38778 CharacterReferenceType["DEC"] = "decimal"; 38779})(CharacterReferenceType || (CharacterReferenceType = {})); 38780 38781class _ControlFlowError { 38782 constructor(error) { 38783 this.error = error; 38784 } 38785 38786} // See https://www.w3.org/TR/html51/syntax.html#writing-html-documents 38787 38788 38789class _Tokenizer { 38790 /** 38791 * @param _file The html source file being tokenized. 38792 * @param _getTagDefinition A function that will retrieve a tag definition for a given tag name. 38793 * @param options Configuration of the tokenization. 38794 */ 38795 constructor(_file, _getTagDefinition, options) { 38796 this._getTagDefinition = _getTagDefinition; 38797 this._currentTokenStart = null; 38798 this._currentTokenType = null; 38799 this._expansionCaseStack = []; 38800 this._inInterpolation = false;
38801 this.tokens = []; 38802 this.errors = []; 38803 this.nonNormalizedIcuExpressions = []; 38804 this._tokenizeIcu = options.tokenizeExpansionForms || false; 38805 this._interpolationConfig = options.interpolationConfig || DEFAULT_INTERPOLATION_CONFIG; 38806 this._leadingTriviaCodePoints = options.leadingTriviaChars && options.leadingTriviaChars.map(c => c.codePointAt(0) || 0); 38807 const range = options.range || { 38808 endPos: _file.content.length, 38809 startPos: 0, 38810 startLine: 0, 38811 startCol: 0 38812 }; 38813 this._cursor = options.escapedString ? new EscapedCharacterCursor(_file, range) : new PlainCharacterCursor(_file, range); 38814 this._preserveLineEndings = options.preserveLineEndings || false; 38815 this._escapedString = options.escapedString || false; 38816 this._i18nNormalizeLineEndingsInICUs = options.i18nNormalizeLineEndingsInICUs || false; 38817 38818 try { 38819 this._cursor.init(); 38820 } catch (e) { 38821 this.handleError(e); 38822 } 38823 } 38824 38825 _processCarriageReturns(content) { 38826 if (this._preserveLineEndings) { 38827 return content; 38828 } // https://www.w3.org/TR/html51/syntax.html#preprocessing-the-input-stream 38829 // In order to keep the original position in the source, we can not 38830 // pre-process it. 38831 // Instead CRs are processed right before instantiating the tokens. 38832 38833 38834 return content.replace(_CR_OR_CRLF_REGEXP, '\n'); 38835 } 38836 38837 tokenize() { 38838 while (this._cursor.peek() !== $EOF) { 38839 const start = this._cursor.clone(); 38840 38841 try { 38842 if (this._attemptCharCode($LT)) { 38843 if (this._attemptCharCode($BANG)) { 38844 if (this._attemptCharCode($LBRACKET)) { 38845 this._consumeCdata(start); 38846 } else if (this._attemptCharCode($MINUS)) { 38847 this._consumeComment(start); 38848 } else { 38849 this._consumeDocType(start); 38850 } 38851 } else if (this._attemptCharCode($SLASH)) { 38852 this._consumeTagClose(start); 38853 } else { 38854 this._consumeTagOpen(start); 38855 } 38856 } else if (!(this._tokenizeIcu && this._tokenizeExpansionForm())) { 38857 // In (possibly interpolated) text the end of the text is given by `isTextEnd()`, while 38858 // the premature end of an interpolation is given by the start of a new HTML element. 38859 this._consumeWithInterpolation(5 38860 /* TokenType.TEXT */ 38861 , 8 38862 /* TokenType.INTERPOLATION */ 38863 , () => this._isTextEnd(), () => this._isTagStart()); 38864 } 38865 } catch (e) { 38866 this.handleError(e); 38867 } 38868 } 38869 38870 this._beginToken(24 38871 /* TokenType.EOF */ 38872 ); 38873 38874 this._endToken([]); 38875 } 38876 /** 38877 * @returns whether an ICU token has been created 38878 * @internal 38879 */ 38880 38881 38882 _tokenizeExpansionForm() { 38883 if (this.isExpansionFormStart()) { 38884 this._consumeExpansionFormStart(); 38885 38886 return true; 38887 } 38888 38889 if (isExpansionCaseStart(this._cursor.peek()) && this._isInExpansionForm()) { 38890 this._consumeExpansionCaseStart(); 38891 38892 return true; 38893 } 38894 38895 if (this._cursor.peek() === $RBRACE) { 38896 if (this._isInExpansionCase()) { 38897 this._consumeExpansionCaseEnd(); 38898 38899 return true; 38900 } 38901 38902 if (this._isInExpansionForm()) { 38903 this._consumeExpansionFormEnd(); 38904 38905 return true; 38906 } 38907 } 38908 38909 return false; 38910 } 38911 38912 _beginToken(type, start = this._cursor.clone()) { 38913 this._currentTokenStart = start; 38914 this._currentTokenType = type; 38915 } 38916 38917 _endToken(parts, end) { 38918 if (this._currentTokenStart === null) { 38919 throw new TokenError('Programming error - attempted to end a token when there was no start to the token', this._currentTokenType, this._cursor.getSpan(end)); 38920 } 38921 38922 if (this._currentTokenType === null) { 38923 throw new TokenError('Programming error - attempted to end a token which has no token type', null, this._cursor.getSpan(this._currentTokenStart)); 38924 } 38925 38926 const token = { 38927 type: this._currentTokenType, 38928 parts, 38929 sourceSpan: (end ?? this._cursor).getSpan(this._currentTokenStart, this._leadingTriviaCodePoints) 38930 }; 38931 this.tokens.push(token); 38932 this._currentTokenStart = null; 38933 this._currentTokenType = null; 38934 return token; 38935 } 38936 38937 _createError(msg, span) { 38938 if (this._isInExpansionForm()) { 38939 msg += ` (Do you have an unescaped "{" in your template? Use "{{ '{' }}") to escape it.)`; 38940 } 38941 38942 const error = new TokenError(msg, this._currentTokenType, span); 38943 this._currentTokenStart = null; 38944 this._currentTokenType = null; 38945 return new _ControlFlowError(error); 38946 } 38947 38948 handleError(e) { 38949 if (e instanceof CursorError) { 38950 e = this._createError(e.msg, this._cursor.getSpan(e.cursor)); 38951 } 38952 38953 if (e instanceof _ControlFlowError) { 38954 this.errors.push(e.error); 38955 } else { 38956 throw e; 38957 } 38958 } 38959 38960 _attemptCharCode(charCode) { 38961 if (this._cursor.peek() === charCode) { 38962 this._cursor.advance(); 38963 38964 return true; 38965 } 38966 38967 return false;
38968 } 38969 38970 _attemptCharCodeCaseInsensitive(charCode) { 38971 if (compareCharCodeCaseInsensitive(this._cursor.peek(), charCode)) { 38972 this._cursor.advance(); 38973 38974 return true; 38975 } 38976 38977 return false; 38978 } 38979 38980 _requireCharCode(charCode) { 38981 const location = this._cursor.clone(); 38982 38983 if (!this._attemptCharCode(charCode)) { 38984 throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(location)); 38985 } 38986 } 38987 38988 _attemptStr(chars) { 38989 const len = chars.length; 38990 38991 if (this._cursor.charsLeft() < len) { 38992 return false; 38993 } 38994 38995 const initialPosition = this._cursor.clone(); 38996 38997 for (let i = 0; i < len; i++) { 38998 if (!this._attemptCharCode(chars.charCodeAt(i))) { 38999 // If attempting to parse the string fails, we want to reset the parser 39000 // to where it was before the attempt 39001 this._cursor = initialPosition; 39002 return false; 39003 } 39004 } 39005 39006 return true; 39007 } 39008 39009 _attemptStrCaseInsensitive(chars) { 39010 for (let i = 0; i < chars.length; i++) { 39011 if (!this._attemptCharCodeCaseInsensitive(chars.charCodeAt(i))) { 39012 return false; 39013 } 39014 } 39015 39016 return true; 39017 } 39018 39019 _requireStr(chars) { 39020 const location = this._cursor.clone(); 39021 39022 if (!this._attemptStr(chars)) { 39023 throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(location)); 39024 } 39025 } 39026 39027 _attemptCharCodeUntilFn(predicate) { 39028 while (!predicate(this._cursor.peek())) { 39029 this._cursor.advance(); 39030 } 39031 } 39032 39033 _requireCharCodeUntilFn(predicate, len) { 39034 const start = this._cursor.clone(); 39035 39036 this._attemptCharCodeUntilFn(predicate); 39037 39038 if (this._cursor.diff(start) < len) { 39039 throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start)); 39040 } 39041 } 39042 39043 _attemptUntilChar(char) { 39044 while (this._cursor.peek() !== char) { 39045 this._cursor.advance(); 39046 } 39047 } 39048 39049 _readChar() { 39050 // Don't rely upon reading directly from `_input` as the actual char value 39051 // may have been generated from an escape sequence. 39052 const char = String.fromCodePoint(this._cursor.peek()); 39053 39054 this._cursor.advance(); 39055 39056 return char; 39057 } 39058 39059 _consumeEntity(textTokenType) { 39060 this._beginToken(9 39061 /* TokenType.ENCODED_ENTITY */ 39062 ); 39063 39064 const start = this._cursor.clone(); 39065 39066 this._cursor.advance(); 39067 39068 if (this._attemptCharCode($HASH)) { 39069 const isHex = this._attemptCharCode($x) || this._attemptCharCode($X); 39070 39071 const codeStart = this._cursor.clone(); 39072 39073 this._attemptCharCodeUntilFn(isDigitEntityEnd); 39074 39075 if (this._cursor.peek() != $SEMICOLON) { 39076 // Advance cursor to include the peeked character in the string provided to the error 39077 // message. 39078 this._cursor.advance(); 39079 39080 const entityType = isHex ? CharacterReferenceType.HEX : CharacterReferenceType.DEC; 39081 throw this._createError(_unparsableEntityErrorMsg(entityType, this._cursor.getChars(start)), this._cursor.getSpan()); 39082 } 39083 39084 const strNum = this._cursor.getChars(codeStart); 39085 39086 this._cursor.advance(); 39087 39088 try { 39089 const charCode = parseInt(strNum, isHex ? 16 : 10); 39090 39091 this._endToken([String.fromCharCode(charCode), this._cursor.getChars(start)]); 39092 } catch { 39093 throw this._createError(_unknownEntityErrorMsg(this._cursor.getChars(start)), this._cursor.getSpan()); 39094 } 39095 } else { 39096 const nameStart = this._cursor.clone(); 39097 39098 this._attemptCharCodeUntilFn(isNamedEntityEnd); 39099 39100 if (this._cursor.peek() != $SEMICOLON) { 39101 // No semicolon was found so abort the encoded entity token that was in progress, and treat 39102 // this as a text token 39103 this._beginToken(textTokenType, start); 39104 39105 this._cursor = nameStart; 39106 39107 this._endToken(['&']); 39108 } else { 39109 const name = this._cursor.getChars(nameStart); 39110 39111 this._cursor.advance(); 39112 39113 const char = NAMED_ENTITIES[name]; 39114 39115 if (!char) { 39116 throw this._createError(_unknownEntityErrorMsg(name), this._cursor.getSpan(start)); 39117 } 39118 39119 this._endToken([char, `&${name};`]); 39120 } 39121 } 39122 } 39123 39124 _consumeRawText(consumeEntities, endMarkerPredicate) { 39125 this._beginToken(consumeEntities ? 6 39126 /* TokenType.ESCAPABLE_RAW_TEXT */ 39127 : 7 39128 /* TokenType.RAW_TEXT */ 39129 ); 39130 39131 const parts = []; 39132 39133 while (true) { 39134 const tagCloseStart = this._cursor.clone(); 39135 39136 const foundEndMarker = endMarkerPredicate(); 39137 this._cursor = tagCloseStart; 39138 39139 if (foundEndMarker) { 39140 break; 39141 } 39142 39143 if (consumeEntities && this._cursor.peek() === $AMPERSAND) { 39144 this._endToken([this._processCarriageReturns(parts.join(''))]); 39145 39146 parts.length = 0; 39147 39148 this._consumeEntity(6 39149 /* TokenType.ESCAPABLE_RAW_TEXT */ 39150 ); 39151 39152 this._beginToken(6 39153 /* TokenType.ESCAPABLE_RAW_TEXT */ 39154 ); 39155 } else { 39156 parts.push(this._readChar()); 39157 } 39158 } 39159 39160 this._endToken([this._processCarriageReturns(parts.join(''))]); 39161 } 39162 39163 _consumeComment(start) { 39164 this._beginToken(10 39165 /* TokenType.COMMENT_START */ 39166 , start); 39167 39168 this._requireCharCode($MINUS); 39169 39170 this._endToken([]); 39171 39172 this._consumeRawText(false, () => this._attemptStr('-->')); 39173 39174 this._beginToken(11 39175 /* TokenType.COMMENT_END */ 39176 ); 39177 39178 this._requireStr('-->'); 39179 39180 this._endToken([]); 39181 } 39182 39183 _consumeCdata(start) { 39184 this._beginToken(12 39185 /* TokenType.CDATA_START */ 39186 , start); 39187 39188 this._requireStr('CDATA['); 39189 39190 this._endToken([]); 39191 39192 this._consumeRawText(false, () => this._attemptStr(']]>')); 39193 39194 this._beginToken(13 39195 /* TokenType.CDATA_END */ 39196 ); 39197 39198 this._requireStr(']]>'); 39199 39200 this._endToken([]); 39201 } 39202 39203 _consumeDocType(start) { 39204 this._beginToken(18 39205 /* TokenType.DOC_TYPE */ 39206 , start); 39207 39208 const contentStart = this._cursor.clone(); 39209 39210 this._attemptUntilChar($GT); 39211 39212 const content = this._cursor.getChars(contentStart); 39213 39214 this._cursor.advance(); 39215 39216 this._endToken([content]); 39217 } 39218 39219 _consumePrefixAndName() { 39220 const nameOrPrefixStart = this._cursor.clone(); 39221 39222 let prefix = ''; 39223 39224 while (this._cursor.peek() !== $COLON && !isPrefixEnd(this._cursor.peek())) { 39225 this._cursor.advance(); 39226 } 39227 39228 let nameStart; 39229 39230 if (this._cursor.peek() === $COLON) { 39231 prefix = this._cursor.getChars(nameOrPrefixStart); 39232 39233 this._cursor.advance(); 39234 39235 nameStart = this._cursor.clone(); 39236 } else { 39237 nameStart = nameOrPrefixStart; 39238 } 39239 39240 this._requireCharCodeUntilFn(isNameEnd, prefix === '' ? 0 : 1); 39241 39242 const name = this._cursor.getChars(nameStart); 39243 39244 return [prefix, name]; 39245 } 39246 39247 _consumeTagOpen(start) { 39248 let tagName; 39249 let prefix; 39250 let openTagToken; 39251 39252 try { 39253 if (!isAsciiLetter(this._cursor.peek())) { 39254 throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start)); 39255 } 39256 39257 openTagToken = this._consumeTagOpenStart(start); 39258 prefix = openTagToken.parts[0]; 39259 tagName = openTagToken.parts[1]; 39260 39261 this._attemptCharCodeUntilFn(isNotWhitespace); 39262 39263 while (this._cursor.peek() !== $SLASH && this._cursor.peek() !== $GT && this._cursor.peek() !== $LT && this._cursor.peek() !== $EOF) { 39264 this._consumeAttributeName(); 39265 39266 this._attemptCharCodeUntilFn(isNotWhitespace); 39267 39268 if (this._attemptCharCode($EQ)) { 39269 this._attemptCharCodeUntilFn(isNotWhitespace); 39270 39271 this._consumeAttributeValue(); 39272 } 39273 39274 this._attemptCharCodeUntilFn(isNotWhitespace); 39275 } 39276 39277 this._consumeTagOpenEnd(); 39278 } catch (e) { 39279 if (e instanceof _ControlFlowError) { 39280 if (openTagToken) { 39281 // We errored before we could close the opening tag, so it is incomplete. 39282 openTagToken.type = 4 39283 /* TokenType.INCOMPLETE_TAG_OPEN */ 39284 ; 39285 } else {
39286 // When the start tag is invalid, assume we want a "<" as text. 39287 // Back to back text tokens are merged at the end. 39288 this._beginToken(5 39289 /* TokenType.TEXT */ 39290 , start); 39291 39292 this._endToken(['<']); 39293 } 39294 39295 return; 39296 } 39297 39298 throw e; 39299 } 39300 39301 const contentTokenType = this._getTagDefinition(tagName).getContentType(prefix); 39302 39303 if (contentTokenType === TagContentType.RAW_TEXT) { 39304 this._consumeRawTextWithTagClose(prefix, tagName, false); 39305 } else if (contentTokenType === TagContentType.ESCAPABLE_RAW_TEXT) { 39306 this._consumeRawTextWithTagClose(prefix, tagName, true); 39307 } 39308 } 39309 39310 _consumeRawTextWithTagClose(prefix, tagName, consumeEntities) { 39311 this._consumeRawText(consumeEntities, () => { 39312 if (!this._attemptCharCode($LT)) return false; 39313 if (!this._attemptCharCode($SLASH)) return false; 39314 39315 this._attemptCharCodeUntilFn(isNotWhitespace); 39316 39317 if (!this._attemptStrCaseInsensitive(tagName)) return false; 39318 39319 this._attemptCharCodeUntilFn(isNotWhitespace); 39320 39321 return this._attemptCharCode($GT); 39322 }); 39323 39324 this._beginToken(3 39325 /* TokenType.TAG_CLOSE */ 39326 ); 39327 39328 this._requireCharCodeUntilFn(code => code === $GT, 3); 39329 39330 this._cursor.advance(); // Consume the `>` 39331 39332 39333 this._endToken([prefix, tagName]); 39334 } 39335 39336 _consumeTagOpenStart(start) { 39337 this._beginToken(0 39338 /* TokenType.TAG_OPEN_START */ 39339 , start); 39340 39341 const parts = this._consumePrefixAndName(); 39342 39343 return this._endToken(parts); 39344 } 39345 39346 _consumeAttributeName() { 39347 const attrNameStart = this._cursor.peek(); 39348 39349 if (attrNameStart === $SQ || attrNameStart === $DQ) { 39350 throw this._createError(_unexpectedCharacterErrorMsg(attrNameStart), this._cursor.getSpan()); 39351 } 39352 39353 this._beginToken(14 39354 /* TokenType.ATTR_NAME */ 39355 ); 39356 39357 const prefixAndName = this._consumePrefixAndName(); 39358 39359 this._endToken(prefixAndName); 39360 } 39361 39362 _consumeAttributeValue() { 39363 let value; 39364 39365 if (this._cursor.peek() === $SQ || this._cursor.peek() === $DQ) { 39366 const quoteChar = this._cursor.peek(); 39367 39368 this._consumeQuote(quoteChar); // In an attribute then end of the attribute value and the premature end to an interpolation 39369 // are both triggered by the `quoteChar`. 39370 39371 39372 const endPredicate = () => this._cursor.peek() === quoteChar; 39373 39374 this._consumeWithInterpolation(16 39375 /* TokenType.ATTR_VALUE_TEXT */ 39376 , 17 39377 /* TokenType.ATTR_VALUE_INTERPOLATION */ 39378 , endPredicate, endPredicate); 39379 39380 this._consumeQuote(quoteChar); 39381 } else { 39382 const endPredicate = () => isNameEnd(this._cursor.peek()); 39383 39384 this._consumeWithInterpolation(16 39385 /* TokenType.ATTR_VALUE_TEXT */ 39386 , 17 39387 /* TokenType.ATTR_VALUE_INTERPOLATION */ 39388 , endPredicate, endPredicate); 39389 } 39390 } 39391 39392 _consumeQuote(quoteChar) { 39393 this._beginToken(15 39394 /* TokenType.ATTR_QUOTE */ 39395 ); 39396 39397 this._requireCharCode(quoteChar); 39398 39399 this._endToken([String.fromCodePoint(quoteChar)]); 39400 } 39401 39402 _consumeTagOpenEnd() { 39403 const tokenType = this._attemptCharCode($SLASH) ? 2 39404 /* TokenType.TAG_OPEN_END_VOID */ 39405 : 1 39406 /* TokenType.TAG_OPEN_END */ 39407 ; 39408 39409 this._beginToken(tokenType); 39410 39411 this._requireCharCode($GT); 39412 39413 this._endToken([]); 39414 } 39415 39416 _consumeTagClose(start) { 39417 this._beginToken(3 39418 /* TokenType.TAG_CLOSE */ 39419 , start); 39420 39421 this._attemptCharCodeUntilFn(isNotWhitespace); 39422 39423 const prefixAndName = this._consumePrefixAndName(); 39424 39425 this._attemptCharCodeUntilFn(isNotWhitespace); 39426 39427 this._requireCharCode($GT); 39428 39429 this._endToken(prefixAndName); 39430 } 39431 39432 _consumeExpansionFormStart() { 39433 this._beginToken(19 39434 /* TokenType.EXPANSION_FORM_START */ 39435 ); 39436 39437 this._requireCharCode($LBRACE); 39438 39439 this._endToken([]); 39440 39441 this._expansionCaseStack.push(19 39442 /* TokenType.EXPANSION_FORM_START */ 39443 ); 39444 39445 this._beginToken(7 39446 /* TokenType.RAW_TEXT */ 39447 ); 39448 39449 const condition = this._readUntil($COMMA); 39450 39451 const normalizedCondition = this._processCarriageReturns(condition); 39452 39453 if (this._i18nNormalizeLineEndingsInICUs) { 39454 // We explicitly want to normalize line endings for this text. 39455 this._endToken([normalizedCondition]); 39456 } else { 39457 // We are not normalizing line endings. 39458 const conditionToken = this._endToken([condition]); 39459 39460 if (normalizedCondition !== condition) { 39461 this.nonNormalizedIcuExpressions.push(conditionToken); 39462 } 39463 } 39464 39465 this._requireCharCode($COMMA); 39466 39467 this._attemptCharCodeUntilFn(isNotWhitespace); 39468 39469 this._beginToken(7 39470 /* TokenType.RAW_TEXT */ 39471 ); 39472 39473 const type = this._readUntil($COMMA); 39474 39475 this._endToken([type]); 39476 39477 this._requireCharCode($COMMA); 39478 39479 this._attemptCharCodeUntilFn(isNotWhitespace); 39480 } 39481 39482 _consumeExpansionCaseStart() { 39483 this._beginToken(20 39484 /* TokenType.EXPANSION_CASE_VALUE */ 39485 ); 39486 39487 const value = this._readUntil($LBRACE).trim(); 39488 39489 this._endToken([value]); 39490 39491 this._attemptCharCodeUntilFn(isNotWhitespace); 39492 39493 this._beginToken(21 39494 /* TokenType.EXPANSION_CASE_EXP_START */ 39495 ); 39496 39497 this._requireCharCode($LBRACE); 39498 39499 this._endToken([]); 39500 39501 this._attemptCharCodeUntilFn(isNotWhitespace); 39502 39503 this._expansionCaseStack.push(21 39504 /* TokenType.EXPANSION_CASE_EXP_START */ 39505 ); 39506 } 39507 39508 _consumeExpansionCaseEnd() { 39509 this._beginToken(22 39510 /* TokenType.EXPANSION_CASE_EXP_END */ 39511 ); 39512 39513 this._requireCharCode($RBRACE); 39514 39515 this._endToken([]); 39516 39517 this._attemptCharCodeUntilFn(isNotWhitespace); 39518 39519 this._expansionCaseStack.pop(); 39520 } 39521 39522 _consumeExpansionFormEnd() { 39523 this._beginToken(23 39524 /* TokenType.EXPANSION_FORM_END */ 39525 ); 39526 39527 this._requireCharCode($RBRACE); 39528 39529 this._endToken([]); 39530 39531 this._expansionCaseStack.pop(); 39532 } 39533 /** 39534 * Consume a string that may contain interpolation expressions. 39535 * 39536 * The first token consumed will be of `tokenType` and then there will be alternating 39537 * `interpolationTokenType` and `tokenType` tokens until the `endPredicate()` returns true. 39538 * 39539 * If an interpolation token ends prematurely it will have no end marker in its `parts` array. 39540 * 39541 * @param textTokenType the kind of tokens to interleave around interpolation tokens. 39542 * @param interpolationTokenType the kind of tokens that contain interpolation. 39543 * @param endPredicate a function that should return true when we should stop consuming. 39544 * @param endInterpolation a function that should return true if there is a premature end to an 39545 * interpolation expression - i.e. before we get to the normal interpolation closing marker. 39546 */ 39547 39548 39549 _consumeWithInterpolation(textTokenType, interpolationTokenType, endPredicate, endInterpolation) { 39550 this._beginToken(textTokenType); 39551 39552 const parts = []; 39553
39554 while (!endPredicate()) { 39555 const current = this._cursor.clone(); 39556 39557 if (this._interpolationConfig && this._attemptStr(this._interpolationConfig.start)) { 39558 this._endToken([this._processCarriageReturns(parts.join(''))], current); 39559 39560 parts.length = 0; 39561 39562 this._consumeInterpolation(interpolationTokenType, current, endInterpolation); 39563 39564 this._beginToken(textTokenType); 39565 } else if (this._cursor.peek() === $AMPERSAND) { 39566 this._endToken([this._processCarriageReturns(parts.join(''))]); 39567 39568 parts.length = 0; 39569 39570 this._consumeEntity(textTokenType); 39571 39572 this._beginToken(textTokenType); 39573 } else { 39574 parts.push(this._readChar()); 39575 } 39576 } // It is possible that an interpolation was started but not ended inside this text token. 39577 // Make sure that we reset the state of the lexer correctly. 39578 39579 39580 this._inInterpolation = false; 39581 39582 this._endToken([this._processCarriageReturns(parts.join(''))]); 39583 } 39584 /** 39585 * Consume a block of text that has been interpreted as an Angular interpolation. 39586 * 39587 * @param interpolationTokenType the type of the interpolation token to generate. 39588 * @param interpolationStart a cursor that points to the start of this interpolation. 39589 * @param prematureEndPredicate a function that should return true if the next characters indicate 39590 * an end to the interpolation before its normal closing marker. 39591 */ 39592 39593 39594 _consumeInterpolation(interpolationTokenType, interpolationStart, prematureEndPredicate) { 39595 const parts = []; 39596 39597 this._beginToken(interpolationTokenType, interpolationStart); 39598 39599 parts.push(this._interpolationConfig.start); // Find the end of the interpolation, ignoring content inside quotes. 39600 39601 const expressionStart = this._cursor.clone(); 39602 39603 let inQuote = null; 39604 let inComment = false; 39605 39606 while (this._cursor.peek() !== $EOF && (prematureEndPredicate === null || !prematureEndPredicate())) { 39607 const current = this._cursor.clone(); 39608 39609 if (this._isTagStart()) { 39610 // We are starting what looks like an HTML element in the middle of this interpolation. 39611 // Reset the cursor to before the `<` character and end the interpolation token. 39612 // (This is actually wrong but here for backward compatibility). 39613 this._cursor = current; 39614 parts.push(this._getProcessedChars(expressionStart, current)); 39615 39616 this._endToken(parts); 39617 39618 return; 39619 } 39620 39621 if (inQuote === null) { 39622 if (this._attemptStr(this._interpolationConfig.end)) { 39623 // We are not in a string, and we hit the end interpolation marker 39624 parts.push(this._getProcessedChars(expressionStart, current)); 39625 parts.push(this._interpolationConfig.end); 39626 39627 this._endToken(parts); 39628 39629 return; 39630 } else if (this._attemptStr('//')) { 39631 // Once we are in a comment we ignore any quotes 39632 inComment = true; 39633 } 39634 } 39635 39636 const char = this._cursor.peek(); 39637 39638 this._cursor.advance(); 39639 39640 if (char === $BACKSLASH) { 39641 // Skip the next character because it was escaped. 39642 this._cursor.advance(); 39643 } else if (char === inQuote) { 39644 // Exiting the current quoted string 39645 inQuote = null; 39646 } else if (!inComment && inQuote === null && isQuote(char)) { 39647 // Entering a new quoted string 39648 inQuote = char; 39649 } 39650 } // We hit EOF without finding a closing interpolation marker 39651 39652 39653 parts.push(this._getProcessedChars(expressionStart, this._cursor)); 39654 39655 this._endToken(parts); 39656 } 39657 39658 _getProcessedChars(start, end) { 39659 return this._processCarriageReturns(end.getChars(start)); 39660 } 39661 39662 _isTextEnd() { 39663 if (this._isTagStart() || this._cursor.peek() === $EOF) { 39664 return true; 39665 } 39666 39667 if (this._tokenizeIcu && !this._inInterpolation) { 39668 if (this.isExpansionFormStart()) { 39669 // start of an expansion form 39670 return true; 39671 } 39672 39673 if (this._cursor.peek() === $RBRACE && this._isInExpansionCase()) { 39674 // end of and expansion case 39675 return true; 39676 } 39677 } 39678 39679 return false; 39680 } 39681 /** 39682 * Returns true if the current cursor is pointing to the start of a tag 39683 * (opening/closing/comments/cdata/etc). 39684 */ 39685 39686 39687 _isTagStart() { 39688 if (this._cursor.peek() === $LT) { 39689 // We assume that `<` followed by whitespace is not the start of an HTML element. 39690 const tmp = this._cursor.clone(); 39691 39692 tmp.advance(); // If the next character is alphabetic, ! nor / then it is a tag start 39693 39694 const code = tmp.peek(); 39695 39696 if ($a <= code && code <= $z || $A <= code && code <= $Z || code === $SLASH || code === $BANG) { 39697 return true; 39698 } 39699 } 39700 39701 return false;
39702 } 39703 39704 _readUntil(char) { 39705 const start = this._cursor.clone(); 39706 39707 this._attemptUntilChar(char); 39708 39709 return this._cursor.getChars(start); 39710 } 39711 39712 _isInExpansionCase() { 39713 return this._expansionCaseStack.length > 0 && this._expansionCaseStack[this._expansionCaseStack.length - 1] === 21 39714 /* TokenType.EXPANSION_CASE_EXP_START */ 39715 ; 39716 } 39717 39718 _isInExpansionForm() { 39719 return this._expansionCaseStack.length > 0 && this._expansionCaseStack[this._expansionCaseStack.length - 1] === 19 39720 /* TokenType.EXPANSION_FORM_START */ 39721 ; 39722 } 39723 39724 isExpansionFormStart() { 39725 if (this._cursor.peek() !== $LBRACE) { 39726 return false; 39727 } 39728 39729 if (this._interpolationConfig) { 39730 const start = this._cursor.clone(); 39731 39732 const isInterpolation = this._attemptStr(this._interpolationConfig.start); 39733 39734 this._cursor = start; 39735 return !isInterpolation; 39736 } 39737 39738 return true; 39739 } 39740 39741} 39742 39743function isNotWhitespace(code) { 39744 return !isWhitespace(code) || code === $EOF; 39745} 39746 39747function isNameEnd(code) { 39748 return isWhitespace(code) || code === $GT || code === $LT || code === $SLASH || code === $SQ || code === $DQ || code === $EQ || code === $EOF; 39749} 39750 39751function isPrefixEnd(code) { 39752 return (code < $a || $z < code) && (code < $A || $Z < code) && (code < $0 || code > $9); 39753} 39754 39755function isDigitEntityEnd(code) { 39756 return code === $SEMICOLON || code === $EOF || !isAsciiHexDigit(code); 39757} 39758 39759function isNamedEntityEnd(code) { 39760 return code === $SEMICOLON || code === $EOF || !isAsciiLetter(code); 39761} 39762 39763function isExpansionCaseStart(peek) { 39764 return peek !== $RBRACE; 39765} 39766 39767function compareCharCodeCaseInsensitive(code1, code2) { 39768 return toUpperCaseCharCode(code1) === toUpperCaseCharCode(code2); 39769} 39770 39771function toUpperCaseCharCode(code) { 39772 return code >= $a && code <= $z ? code - $a + $A : code; 39773} 39774 39775function mergeTextTokens(srcTokens) { 39776 const dstTokens = []; 39777 let lastDstToken = undefined; 39778 39779 for (let i = 0; i < srcTokens.length; i++) { 39780 const token = srcTokens[i]; 39781 39782 if (lastDstToken && lastDstToken.type === 5 39783 /* TokenType.TEXT */ 39784 && token.type === 5 39785 /* TokenType.TEXT */ 39786 || lastDstToken && lastDstToken.type === 16 39787 /* TokenType.ATTR_VALUE_TEXT */ 39788 && token.type === 16 39789 /* TokenType.ATTR_VALUE_TEXT */ 39790 ) { 39791 lastDstToken.parts[0] += token.parts[0]; 39792 lastDstToken.sourceSpan.end = token.sourceSpan.end; 39793 } else { 39794 lastDstToken = token; 39795 dstTokens.push(lastDstToken); 39796 } 39797 } 39798 39799 return dstTokens; 39800} 39801 39802class PlainCharacterCursor { 39803 constructor(fileOrCursor, range) { 39804 if (fileOrCursor instanceof PlainCharacterCursor) { 39805 this.file = fileOrCursor.file; 39806 this.input = fileOrCursor.input; 39807 this.end = fileOrCursor.end; 39808 const state = fileOrCursor.state; // Note: avoid using `{...fileOrCursor.state}` here as that has a severe performance penalty. 39809 // In ES5 bundles the object spread operator is translated into the `__assign` helper, which 39810 // is not optimized by VMs as efficiently as a raw object literal. Since this constructor is 39811 // called in tight loops, this difference matters. 39812 39813 this.state = { 39814 peek: state.peek, 39815 offset: state.offset, 39816 line: state.line, 39817 column: state.column 39818 }; 39819 } else { 39820 if (!range) { 39821 throw new Error('Programming error: the range argument must be provided with a file argument.'); 39822 } 39823 39824 this.file = fileOrCursor; 39825 this.input = fileOrCursor.content; 39826 this.end = range.endPos; 39827 this.state = { 39828 peek: -1, 39829 offset: range.startPos, 39830 line: range.startLine, 39831 column: range.startCol 39832 }; 39833 } 39834 } 39835 39836 clone() { 39837 return new PlainCharacterCursor(this); 39838 } 39839 39840 peek() { 39841 return this.state.peek; 39842 } 39843 39844 charsLeft() { 39845 return this.end - this.state.offset; 39846 } 39847 39848 diff(other) { 39849 return this.state.offset - other.state.offset; 39850 } 39851 39852 advance() { 39853 this.advanceState(this.state); 39854 } 39855 39856 init() { 39857 this.updatePeek(this.state); 39858 } 39859 39860 getSpan(start, leadingTriviaCodePoints) { 39861 start = start || this; 39862 let fullStart = start; 39863 39864 if (leadingTriviaCodePoints) { 39865 while (this.diff(start) > 0 && leadingTriviaCodePoints.indexOf(start.peek()) !== -1) { 39866 if (fullStart === start) { 39867 start = start.clone(); 39868 } 39869 39870 start.advance(); 39871 } 39872 } 39873 39874 const startLocation = this.locationFromCursor(start); 39875 const endLocation = this.locationFromCursor(this); 39876 const fullStartLocation = fullStart !== start ? this.locationFromCursor(fullStart) : startLocation; 39877 return new ParseSourceSpan(startLocation, endLocation, fullStartLocation); 39878 } 39879 39880 getChars(start) { 39881 return this.input.substring(start.state.offset, this.state.offset); 39882 } 39883 39884 charAt(pos) { 39885 return this.input.charCodeAt(pos); 39886 } 39887 39888 advanceState(state) { 39889 if (state.offset >= this.end) { 39890 this.state = state; 39891 throw new CursorError('Unexpected character "EOF"', this); 39892 } 39893 39894 const currentChar = this.charAt(state.offset); 39895 39896 if (currentChar === $LF) { 39897 state.line++; 39898 state.column = 0; 39899 } else if (!isNewLine(currentChar)) { 39900 state.column++; 39901 } 39902 39903 state.offset++; 39904 this.updatePeek(state); 39905 } 39906 39907 updatePeek(state) { 39908 state.peek = state.offset >= this.end ? $EOF : this.charAt(state.offset); 39909 } 39910 39911 locationFromCursor(cursor) { 39912 return new ParseLocation(cursor.file, cursor.state.offset, cursor.state.line, cursor.state.column); 39913 } 39914 39915} 39916 39917class EscapedCharacterCursor extends PlainCharacterCursor { 39918 constructor(fileOrCursor, range) { 39919 if (fileOrCursor instanceof EscapedCharacterCursor) { 39920 super(fileOrCursor); 39921 this.internalState = { ...fileOrCursor.internalState 39922 }; 39923 } else { 39924 super(fileOrCursor, range); 39925 this.internalState = this.state; 39926 } 39927 } 39928 39929 advance() { 39930 this.state = this.internalState; 39931 super.advance(); 39932 this.processEscapeSequence(); 39933 } 39934 39935 init() { 39936 super.init(); 39937 this.processEscapeSequence(); 39938 } 39939 39940 clone() { 39941 return new EscapedCharacterCursor(this); 39942 } 39943 39944 getChars(start) { 39945 const cursor = start.clone();
39946 let chars = ''; 39947 39948 while (cursor.internalState.offset < this.internalState.offset) { 39949 chars += String.fromCodePoint(cursor.peek()); 39950 cursor.advance(); 39951 } 39952 39953 return chars; 39954 } 39955 /** 39956 * Process the escape sequence that starts at the current position in the text. 39957 * 39958 * This method is called to ensure that `peek` has the unescaped value of escape sequences. 39959 */ 39960 39961 39962 processEscapeSequence() { 39963 const peek = () => this.internalState.peek; 39964 39965 if (peek() === $BACKSLASH) { 39966 // We have hit an escape sequence so we need the internal state to become independent 39967 // of the external state. 39968 this.internalState = { ...this.state 39969 }; // Move past the backslash 39970 39971 this.advanceState(this.internalState); // First check for standard control char sequences 39972 39973 if (peek() === $n) { 39974 this.state.peek = $LF; 39975 } else if (peek() === $r) { 39976 this.state.peek = $CR; 39977 } else if (peek() === $v) { 39978 this.state.peek = $VTAB; 39979 } else if (peek() === $t) { 39980 this.state.peek = $TAB; 39981 } else if (peek() === $b) { 39982 this.state.peek = $BSPACE; 39983 } else if (peek() === $f) { 39984 this.state.peek = $FF; 39985 } // Now consider more complex sequences 39986 else if (peek() === $u) { 39987 // Unicode code-point sequence 39988 this.advanceState(this.internalState); // advance past the `u` char 39989 39990 if (peek() === $LBRACE) { 39991 // Variable length Unicode, e.g. `\x{123}` 39992 this.advanceState(this.internalState); // advance past the `{` char 39993 // Advance past the variable number of hex digits until we hit a `}` char 39994 39995 const digitStart = this.clone(); 39996 let length = 0; 39997 39998 while (peek() !== $RBRACE) { 39999 this.advanceState(this.internalState); 40000 length++; 40001 } 40002 40003 this.state.peek = this.decodeHexDigits(digitStart, length); 40004 } else { 40005 // Fixed length Unicode, e.g. `\u1234` 40006 const digitStart = this.clone(); 40007 this.advanceState(this.internalState); 40008 this.advanceState(this.internalState); 40009 this.advanceState(this.internalState); 40010 this.state.peek = this.decodeHexDigits(digitStart, 4); 40011 } 40012 } else if (peek() === $x) { 40013 // Hex char code, e.g. `\x2F` 40014 this.advanceState(this.internalState); // advance past the `x` char 40015 40016 const digitStart = this.clone(); 40017 this.advanceState(this.internalState); 40018 this.state.peek = this.decodeHexDigits(digitStart, 2); 40019 } else if (isOctalDigit(peek())) { 40020 // Octal char code, e.g. `\012`, 40021 let octal = ''; 40022 let length = 0; 40023 let previous = this.clone(); 40024 40025 while (isOctalDigit(peek()) && length < 3) { 40026 previous = this.clone(); 40027 octal += String.fromCodePoint(peek()); 40028 this.advanceState(this.internalState); 40029 length++; 40030 } 40031 40032 this.state.peek = parseInt(octal, 8); // Backup one char 40033 40034 this.internalState = previous.internalState; 40035 } else if (isNewLine(this.internalState.peek)) { 40036 // Line continuation `\` followed by a new line 40037 this.advanceState(this.internalState); // advance over the newline 40038 40039 this.state = this.internalState; 40040 } else { 40041 // If none of the `if` blocks were executed then we just have an escaped normal character. 40042 // In that case we just, effectively, skip the backslash from the character. 40043 this.state.peek = this.internalState.peek; 40044 } 40045 } 40046 } 40047 40048 decodeHexDigits(start, length) { 40049 const hex = this.input.slice(start.internalState.offset, start.internalState.offset + length); 40050 const charCode = parseInt(hex, 16); 40051 40052 if (!isNaN(charCode)) { 40053 return charCode; 40054 } else { 40055 start.state = start.internalState; 40056 throw new CursorError('Invalid hexadecimal escape sequence', start); 40057 } 40058 } 40059 40060} 40061 40062class CursorError { 40063 constructor(msg, cursor) { 40064 this.msg = msg; 40065 this.cursor = cursor; 40066 } 40067 40068} 40069/** 40070 * @license 40071 * Copyright Google LLC All Rights Reserved. 40072 * 40073 * Use of this source code is governed by an MIT-style license that can be 40074 * found in the LICENSE file at https://angular.io/license 40075 */ 40076 40077 40078class TreeError extends ParseError { 40079 constructor(elementName, span, msg) { 40080 super(span, msg); 40081 this.elementName = elementName; 40082 } 40083 40084 static create(elementName, span, msg) { 40085 return new TreeError(elementName, span, msg); 40086 } 40087 40088} 40089 40090class ParseTreeResult { 40091 constructor(rootNodes, errors) { 40092 this.rootNodes = rootNodes; 40093 this.errors = errors; 40094 } 40095 40096} 40097 40098class Parser { 40099 constructor(getTagDefinition) { 40100 this.getTagDefinition = getTagDefinition; 40101 } 40102 40103 parse(source, url, options) { 40104 const tokenizeResult = tokenize(source, url, this.getTagDefinition, options); 40105 const parser = new _TreeBuilder(tokenizeResult.tokens, this.getTagDefinition); 40106 parser.build(); 40107 return new ParseTreeResult(parser.rootNodes, tokenizeResult.errors.concat(parser.errors)); 40108 } 40109 40110} 40111 40112class _TreeBuilder { 40113 constructor(tokens, getTagDefinition) { 40114 this.tokens = tokens; 40115 this.getTagDefinition = getTagDefinition; 40116 this._index = -1; 40117 this._elementStack = []; 40118 this.rootNodes = []; 40119 this.errors = []; 40120 40121 this._advance(); 40122 } 40123 40124 build() { 40125 while (this._peek.type !== 24 40126 /* TokenType.EOF */ 40127 ) { 40128 if (this._peek.type === 0 40129 /* TokenType.TAG_OPEN_START */ 40130 || this._peek.type === 4 40131 /* TokenType.INCOMPLETE_TAG_OPEN */ 40132 ) { 40133 this._consumeStartTag(this._advance()); 40134 } else if (this._peek.type === 3 40135 /* TokenType.TAG_CLOSE */ 40136 ) { 40137 this._consumeEndTag(this._advance()); 40138 } else if (this._peek.type === 12 40139 /* TokenType.CDATA_START */ 40140 ) { 40141 this._closeVoidElement(); 40142 40143 this._consumeCdata(this._advance()); 40144 } else if (this._peek.type === 10 40145 /* TokenType.COMMENT_START */ 40146 ) { 40147 this._closeVoidElement(); 40148 40149 this._consumeComment(this._advance()); 40150 } else if (this._peek.type === 5 40151 /* TokenType.TEXT */ 40152 || this._peek.type === 7 40153 /* TokenType.RAW_TEXT */ 40154 || this._peek.type === 6 40155 /* TokenType.ESCAPABLE_RAW_TEXT */ 40156 ) { 40157 this._closeVoidElement(); 40158 40159 this._consumeText(this._advance()); 40160 } else if (this._peek.type === 19 40161 /* TokenType.EXPANSION_FORM_START */ 40162 ) { 40163 this._consumeExpansion(this._advance()); 40164 } else { 40165 // Skip all other tokens... 40166 this._advance(); 40167 } 40168 } 40169 } 40170 40171 _advance() { 40172 const prev = this._peek; 40173 40174 if (this._index < this.tokens.length - 1) { 40175 // Note: there is always an EOF token at the end 40176 this._index++; 40177 } 40178 40179 this._peek = this.tokens[this._index]; 40180 return prev; 40181 } 40182 40183 _advanceIf(type) { 40184 if (this._peek.type === type) { 40185 return this._advance(); 40186 } 40187 40188 return null; 40189 } 40190 40191 _consumeCdata(_startToken) { 40192 this._consumeText(this._advance()); 40193 40194 this._advanceIf(13 40195 /* TokenType.CDATA_END */ 40196 ); 40197 } 40198 40199 _consumeComment(token) { 40200 const text = this._advanceIf(7 40201 /* TokenType.RAW_TEXT */ 40202 ); 40203 40204 this._advanceIf(11 40205 /* TokenType.COMMENT_END */ 40206 ); 40207 40208 const value = text != null ? text.parts[0].trim() : null; 40209 40210 this._addToParent(new Comment(value, token.sourceSpan)); 40211 } 40212 40213 _consumeExpansion(token) { 40214 const switchValue = this._advance(); 40215 40216 const type = this._advance(); 40217 40218 const cases = []; // read = 40219 40220 while (this._peek.type === 20 40221 /* TokenType.EXPANSION_CASE_VALUE */ 40222 ) { 40223 const expCase = this._parseExpansionCase(); 40224 40225 if (!expCase) return; // error 40226 40227 cases.push(expCase); 40228 } // read the final } 40229 40230 40231 if (this._peek.type !== 23 40232 /* TokenType.EXPANSION_FORM_END */ 40233 ) { 40234 this.errors.push(TreeError.create(null, this._peek.sourceSpan, `Invalid ICU message. Missing '}'.`)); 40235 return; 40236 } 40237 40238 const sourceSpan = new ParseSourceSpan(token.sourceSpan.start, this._peek.sourceSpan.end, token.sourceSpan.fullStart); 40239 40240 this._addToParent(new Expansion(switchValue.parts[0], type.parts[0], cases, sourceSpan, switchValue.sourceSpan)); 40241 40242 this._advance(); 40243 } 40244 40245 _parseExpansionCase() { 40246 const value = this._advance(); // read { 40247 40248 40249 if (this._peek.type !== 21 40250 /* TokenType.EXPANSION_CASE_EXP_START */ 40251 ) { 40252 this.errors.push(TreeError.create(null, this._peek.sourceSpan, `Invalid ICU message. Missing '{'.`)); 40253 return null; 40254 } // read until } 40255 40256 40257 const start = this._advance(); 40258 40259 const exp = this._collectExpansionExpTokens(start); 40260 40261 if (!exp) return null; 40262 40263 const end = this._advance(); 40264 40265 exp.push({ 40266 type: 24 40267 /* TokenType.EOF */ 40268 , 40269 parts: [], 40270 sourceSpan: end.sourceSpan 40271 }); // parse everything in between { and } 40272 40273 const expansionCaseParser = new _TreeBuilder(exp, this.getTagDefinition); 40274 expansionCaseParser.build(); 40275 40276 if (expansionCaseParser.errors.length > 0) { 40277 this.errors = this.errors.concat(expansionCaseParser.errors); 40278 return null; 40279 } 40280 40281 const sourceSpan = new ParseSourceSpan(value.sourceSpan.start, end.sourceSpan.end, value.sourceSpan.fullStart); 40282 const expSourceSpan = new ParseSourceSpan(start.sourceSpan.start, end.sourceSpan.end, start.sourceSpan.fullStart); 40283 return new ExpansionCase(value.parts[0], expansionCaseParser.rootNodes, sourceSpan, value.sourceSpan, expSourceSpan); 40284 } 40285 40286 _collectExpansionExpTokens(start) { 40287 const exp = []; 40288 const expansionFormStack = [21 40289 /* TokenType.EXPANSION_CASE_EXP_START */ 40290 ]; 40291 40292 while (true) { 40293 if (this._peek.type === 19 40294 /* TokenType.EXPANSION_FORM_START */ 40295 || this._peek.type === 21 40296 /* TokenType.EXPANSION_CASE_EXP_START */ 40297 ) { 40298 expansionFormStack.push(this._peek.type); 40299 } 40300 40301 if (this._peek.type === 22 40302 /* TokenType.EXPANSION_CASE_EXP_END */ 40303 ) { 40304 if (lastOnStack(expansionFormStack, 21 40305 /* TokenType.EXPANSION_CASE_EXP_START */ 40306 )) { 40307 expansionFormStack.pop(); 40308 if (expansionFormStack.length === 0) return exp; 40309 } else { 40310 this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`)); 40311 return null; 40312 } 40313 } 40314 40315 if (this._peek.type === 23 40316 /* TokenType.EXPANSION_FORM_END */ 40317 ) { 40318 if (lastOnStack(expansionFormStack, 19 40319 /* TokenType.EXPANSION_FORM_START */ 40320 )) { 40321 expansionFormStack.pop(); 40322 } else { 40323 this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`)); 40324 return null; 40325 } 40326 } 40327 40328 if (this._peek.type === 24 40329 /* TokenType.EOF */ 40330 ) { 40331 this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`)); 40332 return null; 40333 } 40334 40335 exp.push(this._advance()); 40336 } 40337 } 40338 40339 _consumeText(token) { 40340 const tokens = [token]; 40341 const startSpan = token.sourceSpan; 40342 let text = token.parts[0]; 40343 40344 if (text.length > 0 && text[0] === '\n') { 40345 const parent = this._getParentElement(); 40346 40347 if (parent != null && parent.children.length === 0 && this.getTagDefinition(parent.name).ignoreFirstLf) { 40348 text = text.substring(1); 40349 tokens[0] = { 40350 type: token.type, 40351 sourceSpan: token.sourceSpan, 40352 parts: [text] 40353 }; 40354 } 40355 } 40356 40357 while (this._peek.type === 8 40358 /* TokenType.INTERPOLATION */ 40359 || this._peek.type === 5 40360 /* TokenType.TEXT */ 40361 || this._peek.type === 9 40362 /* TokenType.ENCODED_ENTITY */ 40363 ) { 40364 token = this._advance(); 40365 tokens.push(token); 40366 40367 if (token.type === 8 40368 /* TokenType.INTERPOLATION */ 40369 ) { 40370 // For backward compatibility we decode HTML entities that appear in interpolation 40371 // expressions. This is arguably a bug, but it could be a considerable breaking change to 40372 // fix it. It should be addressed in a larger project to refactor the entire parser/lexer 40373 // chain after View Engine has been removed. 40374 text += token.parts.join('').replace(/&([^;]+);/g, decodeEntity); 40375 } else if (token.type === 9 40376 /* TokenType.ENCODED_ENTITY */ 40377 ) { 40378 text += token.parts[0]; 40379 } else { 40380 text += token.parts.join(''); 40381 } 40382 } 40383 40384 if (text.length > 0) { 40385 const endSpan = token.sourceSpan; 40386 40387 this._addToParent(new Text(text, new ParseSourceSpan(start
40387Span.start, endSpan.end, startSpan.fullStart, startSpan.details), tokens)); 40388 } 40389 } 40390 40391 _closeVoidElement() { 40392 const el = this._getParentElement(); 40393 40394 if (el && this.getTagDefinition(el.name).isVoid) { 40395 this._elementStack.pop(); 40396 } 40397 } 40398 40399 _consumeStartTag(startTagToken) { 40400 const [prefix, name] = startTagToken.parts; 40401 const attrs = []; 40402 40403 while (this._peek.type === 14 40404 /* TokenType.ATTR_NAME */ 40405 ) { 40406 attrs.push(this._consumeAttr(this._advance())); 40407 } 40408 40409 const fullName = this._getElementFullName(prefix, name, this._getParentElement()); 40410 40411 let selfClosing = false; // Note: There could have been a tokenizer error 40412 // so that we don't get a token for the end tag... 40413 40414 if (this._peek.type === 2 40415 /* TokenType.TAG_OPEN_END_VOID */ 40416 ) { 40417 this._advance(); 40418 40419 selfClosing = true; 40420 const tagDef = this.getTagDefinition(fullName); 40421 40422 if (!(tagDef.canSelfClose || getNsPrefix(fullName) !== null || tagDef.isVoid)) { 40423 this.errors.push(TreeError.create(fullName, startTagToken.sourceSpan, `Only void and foreign elements can be self closed "${startTagToken.parts[1]}"`)); 40424 } 40425 } else if (this._peek.type === 1 40426 /* TokenType.TAG_OPEN_END */ 40427 ) { 40428 this._advance(); 40429 40430 selfClosing = false; 40431 } 40432 40433 const end = this._peek.sourceSpan.fullStart; 40434 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. 40435 40436 const startSpan = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart); 40437 const el = new Element(fullName, attrs, [], span, startSpan, undefined); 40438 40439 this._pushElement(el); 40440 40441 if (selfClosing) { 40442 // Elements that are self-closed have their `endSourceSpan` set to the full span, as the 40443 // element start tag also represents the end tag. 40444 this._popElement(fullName, span); 40445 } else if (startTagToken.type === 4 40446 /* TokenType.INCOMPLETE_TAG_OPEN */ 40447 ) { 40448 // We already know the opening tag is not complete, so it is unlikely it has a corresponding 40449 // close tag. Let's optimistically parse it as a full element and emit an error. 40450 this._popElement(fullName, null); 40451 40452 this.errors.push(TreeError.create(fullName, span, `Opening tag "${fullName}" not terminated.`)); 40453 } 40454 } 40455 40456 _pushElement(el) { 40457 const parentEl = this._getParentElement(); 40458 40459 if (parentEl && this.getTagDefinition(parentEl.name).isClosedByChild(el.name)) { 40460 this._elementStack.pop(); 40461 } 40462 40463 this._addToParent(el); 40464 40465 this._elementStack.push(el); 40466 } 40467 40468 _consumeEndTag(endTagToken) { 40469 const fullName = this._getElementFullName(endTagToken.parts[0], endTagToken.parts[1], this._getParentElement()); 40470 40471 if (this.getTagDefinition(fullName).isVoid) { 40472 this.errors.push(TreeError.create(fullName, endTagToken.sourceSpan, `Void elements do not have end tags "${endTagToken.parts[1]}"`)); 40473 } else if (!this._popElement(fullName, endTagToken.sourceSpan)) { 40474 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`; 40475 this.errors.push(TreeError.create(fullName, endTagToken.sourceSpan, errMsg)); 40476 } 40477 } 40478 /** 40479 * Closes the nearest element with the tag name `fullName` in the parse tree. 40480 * `endSourceSpan` is the span of the closing tag, or null if the element does 40481 * not have a closing tag (for example, this happens when an incomplete 40482 * opening tag is recovered). 40483 */ 40484 40485 40486 _popElement(fullName, endSourceSpan) { 40487 let unexpectedCloseTagDetected = false; 40488 40489 for (let stackIndex = this._elementStack.length - 1; stackIndex >= 0; stackIndex--) { 40490 const el = this._elementStack[stackIndex]; 40491 40492 if (el.name === fullName) { 40493 // Record the parse span with the element that is being closed. Any elements that are 40494 // removed from the element stack at this point are closed implicitly, so they won't get 40495 // an end source span (as there is no explicit closing element). 40496 el.endSourceSpan = endSourceSpan; 40497 el.sourceSpan.end = endSourceSpan !== null ? endSourceSpan.end : el.sourceSpan.end; 40498 40499 this._elementStack.splice(stackIndex, this._elementStack.length - stackIndex); 40500 40501 return !unexpectedCloseTagDetected; 40502 } 40503 40504 if (!this.getTagDefinition(el.name).closedByParent) { 40505 // Note that we encountered an unexpected close tag but continue processing the element 40506 // stack so we can assign an `endSourceSpan` if there is a corresponding start tag for this 40507 // end tag in the stack. 40508 unexpectedCloseTagDetected = true; 40509 } 40510 } 40511 40512 return false;
40513 } 40514 40515 _consumeAttr(attrName) { 40516 const fullName = mergeNsAndName(attrName.parts[0], attrName.parts[1]); 40517 let attrEnd = attrName.sourceSpan.end; // Consume any quote 40518 40519 if (this._peek.type === 15 40520 /* TokenType.ATTR_QUOTE */ 40521 ) { 40522 this._advance(); 40523 } // Consume the attribute value 40524 40525 40526 let value = ''; 40527 const valueTokens = []; 40528 let valueStartSpan = undefined; 40529 let valueEnd = undefined; // NOTE: We need to use a new variable `nextTokenType` here to hide the actual type of 40530 // `_peek.type` from TS. Otherwise TS will narrow the type of `_peek.type` preventing it from 40531 // being able to consider `ATTR_VALUE_INTERPOLATION` as an option. This is because TS is not 40532 // able to see that `_advance()` will actually mutate `_peek`. 40533 40534 const nextTokenType = this._peek.type; 40535 40536 if (nextTokenType === 16 40537 /* TokenType.ATTR_VALUE_TEXT */ 40538 ) { 40539 valueStartSpan = this._peek.sourceSpan; 40540 valueEnd = this._peek.sourceSpan.end; 40541 40542 while (this._peek.type === 16 40543 /* TokenType.ATTR_VALUE_TEXT */ 40544 || this._peek.type === 17 40545 /* TokenType.ATTR_VALUE_INTERPOLATION */ 40546 || this._peek.type === 9 40547 /* TokenType.ENCODED_ENTITY */ 40548 ) { 40549 const valueToken = this._advance(); 40550 40551 valueTokens.push(valueToken); 40552 40553 if (valueToken.type === 17 40554 /* TokenType.ATTR_VALUE_INTERPOLATION */ 40555 ) { 40556 // For backward compatibility we decode HTML entities that appear in interpolation 40557 // expressions. This is arguably a bug, but it could be a considerable breaking change to 40558 // fix it. It should be addressed in a larger project to refactor the entire parser/lexer 40559 // chain after View Engine has been removed. 40560 value += valueToken.parts.join('').replace(/&([^;]+);/g, decodeEntity); 40561 } else if (valueToken.type === 9 40562 /* TokenType.ENCODED_ENTITY */ 40563 ) { 40564 value += valueToken.parts[0]; 40565 } else { 40566 value += valueToken.parts.join(''); 40567 } 40568 40569 valueEnd = attrEnd = valueToken.sourceSpan.end; 40570 } 40571 } // Consume any quote 40572 40573 40574 if (this._peek.type === 15 40575 /* TokenType.ATTR_QUOTE */ 40576 ) { 40577 const quoteToken = this._advance(); 40578 40579 attrEnd = quoteToken.sourceSpan.end; 40580 } 40581 40582 const valueSpan = valueStartSpan && valueEnd && new ParseSourceSpan(valueStartSpan.start, valueEnd, valueStartSpan.fullStart); 40583 return new Attribute(fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, attrEnd, attrName.sourceSpan.fullStart), attrName.sourceSpan, valueSpan, valueTokens.length > 0 ? valueTokens : undefined, undefined); 40584 } 40585 40586 _getParentElement() { 40587 return this._elementStack.length > 0 ? this._elementStack[this._elementStack.length - 1] : null; 40588 } 40589 40590 _addToParent(node) { 40591 const parent = this._getParentElement(); 40592 40593 if (parent != null) { 40594 parent.children.push(node); 40595 } else { 40596 this.rootNodes.push(node); 40597 } 40598 } 40599 40600 _getElementFullName(prefix, localName, parentElement) { 40601 if (prefix === '') { 40602 prefix = this.getTagDefinition(localName).implicitNamespacePrefix || ''; 40603 40604 if (prefix === '' && parentElement != null) { 40605 const parentTagName = splitNsName(parentElement.name)[1]; 40606 const parentTagDefinition = this.getTagDefinition(parentTagName); 40607 40608 if (!parentTagDefinition.preventNamespaceInheritance) { 40609 prefix = getNsPrefix(parentElement.name); 40610 } 40611 } 40612 } 40613 40614 return mergeNsAndName(prefix, localName); 40615 } 40616 40617} 40618 40619function lastOnStack(stack, element) { 40620 return stack.length > 0 && stack[stack.length - 1] === element; 40621} 40622/** 40623 * Decode the `entity` string, which we believe is the contents of an HTML entity. 40624 * 40625 * If the string is not actually a valid/known entity then just return the original `match` string. 40626 */ 40627 40628 40629function decodeEntity(match, entity) { 40630 if (NAMED_ENTITIES[entity] !== undefined) { 40631 return NAMED_ENTITIES[entity] || match; 40632 } 40633 40634 if (/^#x[a-f0-9]+$/i.test(entity)) { 40635 return String.fromCodePoint(parseInt(entity.slice(2), 16)); 40636 } 40637 40638 if (/^#\d+$/.test(entity)) { 40639 return String.fromCodePoint(parseInt(entity.slice(1), 10)); 40640 } 40641 40642 return match; 40643} 40644/** 40645 * @license 40646 * Copyright Google LLC All Rights Reserved. 40647 * 40648 * Use of this source code is governed by an MIT-style license that can be 40649 * found in the LICENSE file at https://angular.io/license 40650 */ 40651 40652 40653class HtmlParser extends Parser { 40654 constructor() { 40655 super(getHtmlTagDefinition); 40656 } 40657 40658 parse(source, url, options) { 40659 return super.parse(source, url, options); 40660 } 40661 40662} 40663/** 40664 * @license 40665 * Copyright Google LLC All Rights Reserved. 40666 * 40667 * Use of this source code is governed by an MIT-style license that can be 40668 * found in the LICENSE file at https://angular.io/license 40669 */ 40670 40671
40672const PRESERVE_WS_ATTR_NAME = 'ngPreserveWhitespaces'; 40673const SKIP_WS_TRIM_TAGS = new Set(['pre', 'template', 'textarea', 'script', 'style']); // Equivalent to \s with \u00a0 (non-breaking space) excluded. 40674// Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp 40675 40676const WS_CHARS = ' \f\n\r\t\v\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff'; 40677const NO_WS_REGEXP = new RegExp(`[^${WS_CHARS}]`); 40678const WS_REPLACE_REGEXP = new RegExp(`[${WS_CHARS}]{2,}`, 'g'); 40679 40680function hasPreserveWhitespacesAttr(attrs) { 40681 return attrs.some(attr => attr.name === PRESERVE_WS_ATTR_NAME); 40682} 40683/** 40684 * Angular Dart introduced &ngsp; as a placeholder for non-removable space, see: 40685 * https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart#L25-L32 40686 * In Angular Dart &ngsp; is converted to the 0xE500 PUA (Private Use Areas) unicode character 40687 * and later on replaced by a space. We are re-implementing the same idea here. 40688 */ 40689 40690 40691function replaceNgsp(value) { 40692 // lexer is replacing the &ngsp; pseudo-entity with NGSP_UNICODE 40693 return value.replace(new RegExp(NGSP_UNICODE, 'g'), ' '); 40694} 40695/** 40696 * This visitor can walk HTML parse tree and remove / trim text nodes using the following rules: 40697 * - consider spaces, tabs and new lines as whitespace characters; 40698 * - drop text nodes consisting of whitespace characters only; 40699 * - for all other text nodes replace consecutive whitespace characters with one space; 40700 * - convert &ngsp; pseudo-entity to a single space; 40701 * 40702 * Removal and trimming of whitespaces have positive performance impact (less code to generate 40703 * while compiling templates, faster view creation). At the same time it can be "destructive" 40704 * in some cases (whitespaces can influence layout). Because of the potential of breaking layout 40705 * this visitor is not activated by default in Angular 5 and people need to explicitly opt-in for 40706 * whitespace removal. The default option for whitespace removal will be revisited in Angular 6 40707 * and might be changed to "on" by default. 40708 */ 40709 40710 40711class WhitespaceVisitor { 40712 visitElement(element, context) { 40713 if (SKIP_WS_TRIM_TAGS.has(element.name) || hasPreserveWhitespacesAttr(element.attrs)) { 40714 // don't descent into elements where we need to preserve whitespaces 40715 // but still visit all attributes to eliminate one used as a market to preserve WS 40716 return new Element(element.name, visitAll(this, element.attrs), element.children, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n); 40717 } 40718 40719 return new Element(element.name, element.attrs, visitAllWithSiblings(this, element.children), element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n); 40720 } 40721 40722 visitAttribute(attribute, context) { 40723 return attribute.name !== PRESERVE_WS_ATTR_NAME ? attribute : null; 40724 } 40725 40726 visitText(text, context) { 40727 const isNotBlank = text.value.match(NO_WS_REGEXP); 40728 const hasExpansionSibling = context && (context.prev instanceof Expansion || context.next instanceof Expansion); 40729 40730 if (isNotBlank || hasExpansionSibling) { 40731 // Process the whitespace in the tokens of this Text node 40732 const tokens = text.tokens.map(token => token.type === 5 40733 /* TokenType.TEXT */ 40734 ? createWhitespaceProcessedTextToken(token) : token); // Process the whitespace of the value of this Text node 40735 40736 const value = processWhitespace(text.value); 40737 return new Text(value, text.sourceSpan, tokens, text.i18n); 40738 } 40739 40740 return null; 40741 } 40742 40743 visitComment(comment, context) { 40744 return comment; 40745 } 40746 40747 visitExpansion(expansion, context) { 40748 return expansion; 40749 } 40750 40751 visitExpansionCase(expansionCase, context) { 40752 return expansionCase; 40753 } 40754 40755} 40756 40757function createWhitespaceProcessedTextToken({ 40758 type, 40759 parts, 40760 sourceSpan 40761}) { 40762 return { 40763 type, 40764 parts: [processWhitespace(parts[0])], 40765 sourceSpan 40766 }; 40767} 40768 40769function processWhitespace(text) { 40770 return replaceNgsp(text).replace(WS_REPLACE_REGEXP, ' '); 40771} 40772 40773function removeWhitespaces(htmlAstWithErrors) { 40774 return new ParseTreeResult(visitAll(new WhitespaceVisitor(), htmlAstWithErrors.rootNodes), htmlAstWithErrors.errors); 40775} 40776 40777function visitAllWithSiblings(visitor, nodes) { 40778 const result = [];
40779 nodes.forEach((ast, i) => { 40780 const context = { 40781 prev: nodes[i - 1], 40782 next: nodes[i + 1] 40783 }; 40784 const astResult = ast.visit(visitor, context); 40785 40786 if (astResult) { 40787 result.push(astResult); 40788 } 40789 }); 40790 return result; 40791} 40792/** 40793 * @license 40794 * Copyright Google LLC All Rights Reserved. 40795 * 40796 * Use of this source code is governed by an MIT-style license that can be 40797 * found in the LICENSE file at https://angular.io/license 40798 */ 40799 40800 40801function mapEntry(key, value) { 40802 return { 40803 key, 40804 value, 40805 quoted: false 40806 }; 40807} 40808 40809function mapLiteral(obj, quoted = false) { 40810 return literalMap(Object.keys(obj).map(key => ({ 40811 key, 40812 quoted, 40813 value: obj[key] 40814 }))); 40815} 40816/** 40817 * @license 40818 * Copyright Google LLC All Rights Reserved. 40819 * 40820 * Use of this source code is governed by an MIT-style license that can be 40821 * found in the LICENSE file at https://angular.io/license 40822 */ 40823// ================================================================================================= 40824// ================================================================================================= 40825// =========== S T O P - S T O P - S T O P - S T O P - S T O P - S T O P =========== 40826// ================================================================================================= 40827// ================================================================================================= 40828// 40829// DO NOT EDIT THIS LIST OF SECURITY SENSITIVE PROPERTIES WITHOUT A SECURITY REVIEW! 40830// Reach out to mprobst for details. 40831// 40832// ================================================================================================= 40833 40834/** Map from tagName|propertyName to SecurityContext. Properties applying to all tags use '*'. */ 40835 40836 40837let _SECURITY_SCHEMA; 40838 40839function SECURITY_SCHEMA() { 40840 if (!_SECURITY_SCHEMA) { 40841 _SECURITY_SCHEMA = {}; // Case is insignificant below, all element and attribute names are lower-cased for lookup. 40842 40843 registerContext(SecurityContext.HTML, ['iframe|srcdoc', '*|innerHTML', '*|outerHTML']); 40844 registerContext(SecurityContext.STYLE, ['*|style']); // NB: no SCRIPT contexts here, they are never allowed due to the parser stripping them. 40845 40846 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']); 40847 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']); 40848 } 40849 40850 return _SECURITY_SCHEMA; 40851} 40852 40853function registerContext(ctx, specs) { 40854 for (const spec of specs) _SECURITY_SCHEMA[spec.toLowerCase()] = ctx; 40855} 40856/** 40857 * @license 40858 * Copyright Google LLC All Rights Reserved. 40859 * 40860 * Use of this source code is governed by an MIT-style license that can be 40861 * found in the LICENSE file at https://angular.io/license 40862 */ 40863 40864 40865class ElementSchemaRegistry {} 40866/** 40867 * @license 40868 * Copyright Google LLC All Rights Reserved. 40869 * 40870 * Use of this source code is governed by an MIT-style license that can be 40871 * found in the LICENSE file at https://angular.io/license 40872 */ 40873 40874 40875const EVENT = 'event'; 40876const BOOLEAN = 'boolean'; 40877const NUMBER = 'number'; 40878const STRING = 'string'; 40879const OBJECT = 'object'; 40880/** 40881 * This array represents the DOM schema. It encodes inheritance, properties, and events. 40882 * 40883 * ## Overview 40884 * 40885 * Each line represents one kind of element. The `element_inheritance` and properties are joined 40886 * using `element_inheritance|properties` syntax. 40887 * 40888 * ## Element Inheritance 40889 * 40890 * The `element_inheritance` can be further subdivided as `element1,element2,...^parentElement`. 40891 * Here the individual elements are separated by `,` (commas). Every element in the list 40892 * has identical properties. 40893 * 40894 * An `element` may inherit additional properties from `parentElement` If no `^parentElement` is 40895 * specified then `""` (blank) element is assumed. 40896 * 40897 * NOTE: The blank element inherits from root `[Element]` element, the super element of all 40898 * elements. 40899 * 40900 * NOTE an element prefix such as `:svg:` has no special meaning to the schema. 40901 * 40902 * ## Properties 40903 * 40904 * Each element has a set of properties separated by `,` (commas). Each property can be prefixed 40905 * by a special character designating its type: 40906 * 40907 * - (no prefix): property is a string. 40908 * - `*`: property represents an event. 40909 * - `!`: property is a boolean. 40910 * - `#`: property is a number. 40911 * - `%`: property is an object. 40912 * 40913 * ## Query 40914 * 40915 * The class creates an internal squas representation which allows to easily answer the query of 40916 * if a given property exist on a given element. 40917 * 40918 * NOTE: We don't yet support querying for types or events. 40919 * NOTE: This schema is auto extracted from `schema_extractor.ts` located in the test folder, 40920 * see dom_element_schema_registry_spec.ts 40921 */ 40922// ================================================================================================= 40923// ================================================================================================= 40924// =========== S T O P - S T O P - S T O P - S T O P - S T O P - S T O P =========== 40925// ================================================================================================= 40926// ================================================================================================= 40927// 40928// DO NOT EDIT THIS DOM SCHEMA WITHOUT A SECURITY REVIEW! 40929// 40930// Newly added properties must be security reviewed and assigned an appropriate SecurityContext in 40931// dom_security_schema.ts. Reach out to mprobst & rjamet for details. 40932// 40933// ================================================================================================= 40934 40935const SCHEMA = ['[Element]|textContent,%classList,className,id,innerHTML,*beforecopy,*beforecut,*beforepaste,*copy,*cut,*paste,*search,*selectstart,*webkitfullscreenchange,*webkitfullscreenerror,*w
40935heel,outerHTML,#scrollLeft,#scrollTop,slot' + 40936/* added manually to avoid breaking changes */ 40937',*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:|']; 40938 40939const _ATTR_TO_PROP = new Map(Object.entries({ 40940 'class': 'className', 40941 'for': 'htmlFor', 40942 'formaction': 'formAction', 40943 'innerHtml': 'innerHTML', 40944 'readonly': 'readOnly', 40945 'tabindex': 'tabIndex' 40946})); // Invert _ATTR_TO_PROP. 40947 40948 40949const _PROP_TO_ATTR = Array.from(_ATTR_TO_PROP).reduce((inverted, [propertyName, attributeName]) => { 40950 inverted.set(propertyName, attributeName); 40951 return inverted; 40952}, new Map()); 40953
40954class DomElementSchemaRegistry extends ElementSchemaRegistry { 40955 constructor() { 40956 super(); 40957 this._schema = new Map(); // We don't allow binding to events for security reasons. Allowing event bindings would almost 40958 // certainly introduce bad XSS vulnerabilities. Instead, we store events in a separate schema. 40959 40960 this._eventSchema = new Map(); 40961 SCHEMA.forEach(encodedType => { 40962 const type = new Map(); 40963 const events = new Set(); 40964 const [strType, strProperties] = encodedType.split('|'); 40965 const properties = strProperties.split(','); 40966 const [typeNames, superName] = strType.split('^'); 40967 typeNames.split(',').forEach(tag => { 40968 this._schema.set(tag.toLowerCase(), type); 40969 40970 this._eventSchema.set(tag.toLowerCase(), events); 40971 }); 40972 40973 const superType = superName && this._schema.get(superName.toLowerCase()); 40974 40975 if (superType) { 40976 for (const [prop, value] of superType) { 40977 type.set(prop, value); 40978 } 40979 40980 for (const superEvent of this._eventSchema.get(superName.toLowerCase())) { 40981 events.add(superEvent); 40982 } 40983 } 40984 40985 properties.forEach(property => { 40986 if (property.length > 0) { 40987 switch (property[0]) { 40988 case '*': 40989 events.add(property.substring(1)); 40990 break; 40991 40992 case '!': 40993 type.set(property.substring(1), BOOLEAN); 40994 break; 40995 40996 case '#': 40997 type.set(property.substring(1), NUMBER); 40998 break; 40999 41000 case '%': 41001 type.set(property.substring(1), OBJECT); 41002 break; 41003 41004 default: 41005 type.set(property, STRING); 41006 } 41007 } 41008 }); 41009 }); 41010 } 41011 41012 hasProperty(tagName, propName, schemaMetas) { 41013 if (schemaMetas.some(schema => schema.name === NO_ERRORS_SCHEMA.name)) { 41014 return true; 41015 } 41016 41017 if (tagName.indexOf('-') > -1) { 41018 if (isNgContainer(tagName) || isNgContent(tagName)) { 41019 return false; 41020 } 41021 41022 if (schemaMetas.some(schema => schema.name === CUSTOM_ELEMENTS_SCHEMA.name)) { 41023 // Can't tell now as we don't know which properties a custom element will get 41024 // once it is instantiated 41025 return true; 41026 } 41027 } 41028 41029 const elementProperties = this._schema.get(tagName.toLowerCase()) || this._schema.get('unknown'); 41030 41031 return elementProperties.has(propName); 41032 } 41033 41034 hasElement(tagName, schemaMetas) { 41035 if (schemaMetas.some(schema => schema.name === NO_ERRORS_SCHEMA.name)) { 41036 return true; 41037 } 41038 41039 if (tagName.indexOf('-') > -1) { 41040 if (isNgContainer(tagName) || isNgContent(tagName)) { 41041 return true; 41042 } 41043 41044 if (schemaMetas.some(schema => schema.name === CUSTOM_ELEMENTS_SCHEMA.name)) { 41045 // Allow any custom elements 41046 return true; 41047 } 41048 } 41049 41050 return this._schema.has(tagName.toLowerCase()); 41051 } 41052 /** 41053 * securityContext returns the security context for the given property on the given DOM tag. 41054 * 41055 * Tag and property name are statically known and cannot change at runtime, i.e. it is not 41056 * possible to bind a value into a changing attribute or tag name. 41057 * 41058 * The filtering is based on a list of allowed tags|attributes. All attributes in the schema 41059 * above are assumed to have the 'NONE' security context, i.e. that they are safe inert 41060 * string values. Only specific well known attack vectors are assigned their appropriate context. 41061 */ 41062 41063 41064 securityContext(tagName, propName, isAttribute) { 41065 if (isAttribute) { 41066 // NB: For security purposes, use the mapped property name, not the attribute name. 41067 propName = this.getMappedPropName(propName); 41068 } // Make sure comparisons are case insensitive, so that case differences between attribute and 41069 // property names do not have a security impact. 41070 41071 41072 tagName = tagName.toLowerCase(); 41073 propName = propName.toLowerCase(); 41074 let ctx = SECURITY_SCHEMA()[tagName + '|' + propName]; 41075 41076 if (ctx) { 41077 return ctx; 41078 } 41079 41080 ctx = SECURITY_SCHEMA()['*|' + propName]; 41081 return ctx ? ctx : SecurityContext.NONE; 41082 } 41083 41084 getMappedPropName(propName) { 41085 return _ATTR_TO_PROP.get(propName) ?? propName; 41086 } 41087 41088 getDefaultComponentElementName() { 41089 return 'ng-component'; 41090 } 41091 41092 validateProperty(name) { 41093 if (name.toLowerCase().startsWith('on')) { 41094 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.`; 41095 return { 41096 error: true, 41097 msg: msg 41098 }; 41099 } else { 41100 return { 41101 error: false 41102 }; 41103 } 41104 } 41105 41106 validateAttribute(name) { 41107 if (name.toLowerCase().startsWith('on')) { 41108 const msg = `Binding to event attribute '${name}' is disallowed for security reasons, ` + `please use (${name.slice(2)})=...`; 41109 return { 41110 error: true, 41111 msg: msg 41112 }; 41113 } else { 41114 return { 41115 error: false 41116 }; 41117 } 41118 } 41119 41120 allKnownElementNames() { 41121 return Array.from(this._schema.keys()); 41122 } 41123 41124 allKnownAttributesOfElement(tagName) { 41125 const elementProperties = this._schema.get(tagName.toLowerCase()) || this._schema.get('unknown'); // Convert properties to attributes. 41126 41127 41128 return Array.from(elementProperties.keys()).map(prop => _PROP_TO_ATTR.get(prop) ?? prop); 41129 } 41130 41131 allKnownEventsOfElement(tagName) { 41132 return Array.from(this._eventSchema.get(tagName.toLowerCase()) ?? []); 41133 } 41134 41135 normalizeAnimationStyleProperty(propName) { 41136 return dashCaseToCamelCase(propName); 41137 } 41138 41139 normalizeAnimationStyleValue(camelCaseProp, userProvidedProp, val) { 41140 let unit = ''; 41141 const strVal = val.toString().trim(); 41142 let errorMsg = null; 41143 41144 if (_isPixelDimensionStyle(camelCaseProp) && val !== 0 && val !== '0') { 41145 if (typeof val === 'number') { 41146 unit = 'px'; 41147 } else { 41148 const valAndSuffixMatch = val.match(/^[+-]?[\d\.]+([a-z]*)$/); 41149 41150 if (valAndSuffixMatch && valAndSuffixMatch[1].length == 0) { 41151 errorMsg = `Please provide a CSS unit value for ${userProvidedProp}:${val}`; 41152 } 41153 } 41154 } 41155 41156 return { 41157 error: errorMsg, 41158 value: strVal + unit 41159 }; 41160 } 41161 41162} 41163 41164function _isPixelDimensionStyle(prop) { 41165 switch (prop) { 41166 case 'width': 41167 case 'height': 41168 case 'minWidth': 41169 case 'minHeight': 41170 case 'maxWidth': 41171 case 'maxHeight': 41172 case 'left': 41173 case 'top': 41174 case 'bottom': 41175 case 'right': 41176 case 'fontSize': 41177 case 'outlineWidth': 41178 case 'outlineOffset': 41179 case 'paddingTop': 41180 case 'paddingLeft': 41181 case 'paddingBottom': 41182 case 'paddingRight': 41183 case 'marginTop': 41184 case 'marginLeft': 41185 case 'marginBottom': 41186 case 'marginRight': 41187 case 'borderRadius': 41188 case 'borderWidth': 41189 case 'borderTopWidth': 41190 case 'borderLeftWidth': 41191 case 'borderRightWidth': 41192 case 'borderBottomWidth': 41193 case 'textIndent': 41194 return true; 41195 41196 default: 41197 return false;
41198 } 41199} 41200/** 41201 * @license 41202 * Copyright Google LLC All Rights Reserved. 41203 * 41204 * Use of this source code is governed by an MIT-style license that can be 41205 * found in the LICENSE file at https://angular.io/license 41206 */ 41207 41208/** 41209 * Set of tagName|propertyName corresponding to Trusted Types sinks. Properties applying to all 41210 * tags use '*'. 41211 * 41212 * Extracted from, and should be kept in sync with 41213 * https://w3c.github.io/webappsec-trusted-types/dist/spec/#integrations 41214 */ 41215 41216 41217const TRUSTED_TYPES_SINKS = new Set([// NOTE: All strings in this set *must* be lowercase! 41218// TrustedHTML 41219'iframe|srcdoc', '*|innerhtml', '*|outerhtml', // NB: no TrustedScript here, as the corresponding tags are stripped by the compiler. 41220// TrustedScriptURL 41221'embed|src', 'object|codebase', 'object|data']); 41222/** 41223 * isTrustedTypesSink returns true if the given property on the given DOM tag is a Trusted Types 41224 * sink. In that case, use `ElementSchemaRegistry.securityContext` to determine which particular 41225 * Trusted Type is required for values passed to the sink: 41226 * - SecurityContext.HTML corresponds to TrustedHTML 41227 * - SecurityContext.RESOURCE_URL corresponds to TrustedScriptURL 41228 */ 41229 41230function isTrustedTypesSink(tagName, propName) { 41231 // Make sure comparisons are case insensitive, so that case differences between attribute and 41232 // property names do not have a security impact. 41233 tagName = tagName.toLowerCase(); 41234 propName = propName.toLowerCase(); 41235 return TRUSTED_TYPES_SINKS.has(tagName + '|' + propName) || TRUSTED_TYPES_SINKS.has('*|' + propName); 41236} 41237/** 41238 * @license 41239 * Copyright Google LLC All Rights Reserved. 41240 * 41241 * Use of this source code is governed by an MIT-style license that can be 41242 * found in the LICENSE file at https://angular.io/license 41243 */ 41244 41245 41246const PROPERTY_PARTS_SEPARATOR = '.'; 41247const ATTRIBUTE_PREFIX = 'attr'; 41248const CLASS_PREFIX = 'class'; 41249const STYLE_PREFIX = 'style'; 41250const TEMPLATE_ATTR_PREFIX$1 = '*'; 41251const ANIMATE_PROP_PREFIX = 'animate-'; 41252/** 41253 * Parses bindings in templates and in the directive host area. 41254 */ 41255 41256class BindingParser { 41257 constructor(_exprParser, _interpolationConfig, _schemaRegistry, errors) { 41258 this._exprParser = _exprParser; 41259 this._interpolationConfig = _interpolationConfig; 41260 this._schemaRegistry = _schemaRegistry; 41261 this.errors = errors; 41262 } 41263 41264 get interpolationConfig() { 41265 return this._interpolationConfig; 41266 } 41267 41268 createBoundHostProperties(properties, sourceSpan) { 41269 const boundProps = []; 41270 41271 for (const propName of Object.keys(properties)) { 41272 const expression = properties[propName]; 41273 41274 if (typeof expression === 'string') { 41275 this.parsePropertyBinding(propName, expression, true, sourceSpan, sourceSpan.start.offset, undefined, [], // Use the `sourceSpan` for `keySpan`. This isn't really accurate, but neither is the 41276 // sourceSpan, as it represents the sourceSpan of the host itself rather than the 41277 // source of the host binding (which doesn't exist in the template). Regardless, 41278 // neither of these values are used in Ivy but are only here to satisfy the function 41279 // signature. This should likely be refactored in the future so that `sourceSpan` 41280 // isn't being used inaccurately. 41281 boundProps, sourceSpan); 41282 } else { 41283 this._reportError(`Value of the host property binding "${propName}" needs to be a string representing an expression but got "${expression}" (${typeof expression})`, sourceSpan); 41284 } 41285 } 41286 41287 return boundProps; 41288 } 41289 41290 createDirectiveHostEventAsts(hostListeners, sourceSpan) { 41291 const targetEvents = []; 41292 41293 for (const propName of Object.keys(hostListeners)) { 41294 const expression = hostListeners[propName]; 41295 41296 if (typeof expression === 'string') { 41297 // Use the `sourceSpan` for `keySpan` and `handlerSpan`. This isn't really accurate, but 41298 // neither is the `sourceSpan`, as it represents the `sourceSpan` of the host itself 41299 // rather than the source of the host binding (which doesn't exist in the template). 41300 // Regardless, neither of these values are used in Ivy but are only here to satisfy the 41301 // function signature. This should likely be refactored
41301in the future so that `sourceSpan` 41302 // isn't being used inaccurately. 41303 this.parseEvent(propName, expression, 41304 /* isAssignmentEvent */ 41305 false, sourceSpan, sourceSpan, [], targetEvents, sourceSpan); 41306 } else { 41307 this._reportError(`Value of the host listener "${propName}" needs to be a string representing an expression but got "${expression}" (${typeof expression})`, sourceSpan); 41308 } 41309 } 41310 41311 return targetEvents; 41312 } 41313 41314 parseInterpolation(value, sourceSpan, interpolatedTokens) { 41315 const sourceInfo = sourceSpan.start.toString(); 41316 const absoluteOffset = sourceSpan.fullStart.offset; 41317 41318 try { 41319 const ast = this._exprParser.parseInterpolation(value, sourceInfo, absoluteOffset, interpolatedTokens, this._interpolationConfig); 41320 41321 if (ast) this._reportExpressionParserErrors(ast.errors, sourceSpan); 41322 return ast; 41323 } catch (e) { 41324 this._reportError(`${e}`, sourceSpan); 41325 41326 return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset); 41327 } 41328 } 41329 /** 41330 * Similar to `parseInterpolation`, but treats the provided string as a single expression 41331 * element that would normally appear within the interpolation prefix and suffix (`{{` and `}}`). 41332 * This is used for parsing the switch expression in ICUs. 41333 */ 41334 41335 41336 parseInterpolationExpression(expression, sourceSpan) { 41337 const sourceInfo = sourceSpan.start.toString(); 41338 const absoluteOffset = sourceSpan.start.offset; 41339 41340 try { 41341 const ast = this._exprParser.parseInterpolationExpression(expression, sourceInfo, absoluteOffset); 41342 41343 if (ast) this._reportExpressionParserErrors(ast.errors, sourceSpan); 41344 return ast; 41345 } catch (e) { 41346 this._reportError(`${e}`, sourceSpan); 41347 41348 return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset); 41349 } 41350 } 41351 /** 41352 * Parses the bindings in a microsyntax expression, and converts them to 41353 * `ParsedProperty` or `ParsedVariable`. 41354 * 41355 * @param tplKey template binding name 41356 * @param tplValue template binding value 41357 * @param sourceSpan span of template binding relative to entire the template 41358 * @param absoluteValueOffset start of the tplValue relative to the entire template 41359 * @param targetMatchableAttrs potential attributes to match in the template 41360 * @param targetProps target property bindings in the template 41361 * @param targetVars target variables in the template 41362 */ 41363 41364 41365 parseInlineTemplateBinding(tplKey, tplValue, sourceSpan, absoluteValueOffset, targetMatchableAttrs, targetProps, targetVars, isIvyAst) { 41366 const absoluteKeyOffset = sourceSpan.start.offset + TEMPLATE_ATTR_PREFIX$1.length; 41367 41368 const bindings = this._parseTemplateBindings(tplKey, tplValue, sourceSpan, absoluteKeyOffset, absoluteValueOffset); 41369 41370 for (const binding of bindings) { 41371 // sourceSpan is for the entire HTML attribute. bindingSpan is for a particular 41372 // binding within the microsyntax expression so it's more narrow than sourceSpan. 41373 const bindingSpan = moveParseSourceSpan(sourceSpan, binding.sourceSpan); 41374 const key = binding.key.source; 41375 const keySpan = moveParseSourceSpan(sourceSpan, binding.key.span); 41376 41377 if (binding instanceof VariableBinding) { 41378 const value = binding.value ? binding.value.source : '$implicit'; 41379 const valueSpan = binding.value ? moveParseSourceSpan(sourceSpan, binding.value.span) : undefined; 41380 targetVars.push(new ParsedVariable(key, value, bindingSpan, keySpan, valueSpan)); 41381 } else if (binding.value) { 41382 const srcSpan = isIvyAst ? bindingSpan : sourceSpan; 41383 const valueSpan = moveParseSourceSpan(sourceSpan, binding.value.ast.sourceSpan); 41384 41385 this._parsePropertyAst(key, binding.value, srcSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps); 41386 } else { 41387 targetMatchableAttrs.push([key, '' 41388 /* value */ 41389 ]); // Since this is a literal attribute with no RHS, source span should be 41390 // just the key span. 41391 41392 this.parseLiteralAttr(key, null 41393 /* value */ 41394 , keySpan, absoluteValueOffset, undefined 41395 /* valueSpan */ 41396 , targetMatchableAttrs, targetProps, keySpan); 41397 } 41398 } 41399 } 41400 /** 41401 * Parses the bindings in a microsyntax expression, e.g. 41402 * ``` 41403 * <tag *tplKey="let value1 = prop; let value2 = localVar"> 41404 * ``` 41405 * 41406 * @param tplKey template binding name 41407 * @param tplValue template binding value 41408 * @param sourceSpan span of template binding relative to entire the template 41409 * @param absoluteKeyOffset start of the `tplKey` 41410 * @param absoluteValueOffset start of the `tplValue` 41411 */ 41412 41413 41414 _parseTemplateBindings(tplKey, tplValue, sourceSpan, absoluteKeyOffset, absoluteValueOffset) { 41415 const sourceInfo = sourceSpan.start.toString(); 41416 41417 try { 41418 const bindingsResult = this._exprParser.parseTemplateBindings(tplKey, tplValue, sourceInfo, absoluteKeyOffset, absoluteValueOffset); 41419 41420 this._reportExpressionParserErrors(bindingsResult.errors, sourceSpan); 41421
41422 bindingsResult.warnings.forEach(warning => { 41423 this._reportError(warning, sourceSpan, ParseErrorLevel.WARNING); 41424 }); 41425 return bindingsResult.templateBindings; 41426 } catch (e) { 41427 this._reportError(`${e}`, sourceSpan); 41428 41429 return []; 41430 } 41431 } 41432 41433 parseLiteralAttr(name, value, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps, keySpan) { 41434 if (isAnimationLabel(name)) { 41435 name = name.substring(1); 41436 41437 if (keySpan !== undefined) { 41438 keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + 1, keySpan.end.offset)); 41439 } 41440 41441 if (value) { 41442 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); 41443 } 41444 41445 this._parseAnimation(name, value, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps); 41446 } else { 41447 targetProps.push(new ParsedProperty(name, this._exprParser.wrapLiteralPrimitive(value, '', absoluteOffset), ParsedPropertyType.LITERAL_ATTR, sourceSpan, keySpan, valueSpan)); 41448 } 41449 } 41450 41451 parsePropertyBinding(name, expression, isHost, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps, keySpan) { 41452 if (name.length === 0) { 41453 this._reportError(`Property name is missing in binding`, sourceSpan); 41454 } 41455 41456 let isAnimationProp = false; 41457 41458 if (name.startsWith(ANIMATE_PROP_PREFIX)) { 41459 isAnimationProp = true; 41460 name = name.substring(ANIMATE_PROP_PREFIX.length); 41461 41462 if (keySpan !== undefined) { 41463 keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + ANIMATE_PROP_PREFIX.length, keySpan.end.offset)); 41464 } 41465 } else if (isAnimationLabel(name)) { 41466 isAnimationProp = true; 41467 name = name.substring(1); 41468 41469 if (keySpan !== undefined) { 41470 keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + 1, keySpan.end.offset)); 41471 } 41472 } 41473 41474 if (isAnimationProp) { 41475 this._parseAnimation(name, expression, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps); 41476 } else { 41477 this._parsePropertyAst(name, this._parseBinding(expression, isHost, valueSpan || sourceSpan, absoluteOffset), sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps); 41478 } 41479 } 41480 41481 parsePropertyInterpolation(name, value, sourceSpan, valueSpan, targetMatchableAttrs, targetProps, keySpan, interpolatedTokens) { 41482 const expr = this.parseInterpolation(value, valueSpan || sourceSpan, interpolatedTokens); 41483 41484 if (expr) { 41485 this._parsePropertyAst(name, expr, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps); 41486 41487 return true; 41488 } 41489 41490 return false; 41491 } 41492 41493 _parsePropertyAst(name, ast, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps) { 41494 targetMatchableAttrs.push([name, ast.source]); 41495 targetProps.push(new ParsedProperty(name, ast, ParsedPropertyType.DEFAULT, sourceSpan, keySpan, valueSpan)); 41496 } 41497 41498 _parseAnimation(name, expression, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps) { 41499 if (name.length === 0) { 41500 this._reportError('Animation trigger is missing', sourceSpan); 41501 } // This will occur when a @trigger is not paired with an expression. 41502 // For animations it is valid to not have an expression since */void 41503 // states will be applied by angular when the element is attached/detached 41504 41505 41506 const ast = this._parseBinding(expression || 'undefined', false, valueSpan || sourceSpan, absoluteOffset); 41507 41508 targetMatchableAttrs.push([name, ast.source]); 41509 targetProps.push(new ParsedProperty(name, ast, ParsedPropertyType.ANIMATION, sourceSpan, keySpan, valueSpan)); 41510 } 41511 41512 _parseBinding(value, isHostBinding, sourceSpan, absoluteOffset) { 41513 const sourceInfo = (sourceSpan && sourceSpan.start || '(unknown)').toString(); 41514 41515 try { 41516 const ast = isHostBinding ? this._exprParser.parseSimpleBinding(value, sourceInfo, absoluteOffset, this._interpolationConfig) : this._exprParser.parseBinding(value, sourceInfo, absoluteOffset, this._interpolationConfig); 41517 if (ast) this._reportExpressionParserErrors(ast.errors, sourceSpan); 41518 return ast; 41519 } catch (e) { 41520 this._reportError(`${e}`, sourceSpan); 41521 41522 return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset); 41523 } 41524 } 41525 41526 createBoundElementProperty(elementSelector, boundProp, skipValidation = false, mapPropertyName = true) { 41527 if (boundProp.isAnimation) { 41528 return new BoundElementProperty(boundProp.name, 4 41529 /* BindingType.Animation */ 41530 , SecurityContext.NONE, boundProp.expression, null, boundProp.sourceSpan, boundProp.keySpan, boundProp.valueSpan); 41531 } 41532 41533 let unit = null; 41534 let bindingType = undefined; 41535 let boundPropertyName = null; 41536 const parts = boundProp.name.split(PROPERTY_PARTS_SEPARATOR); 41537 let securityContexts = undefined; // Check for special cases (prefix style, attr, class) 41538 41539 if (parts.length > 1) { 41540 if (parts[0] == ATTRIBUTE_PREFIX) { 41541 boundPropertyName = parts.slice(1).join(PROPERTY_PARTS_SEPARATOR); 41542 41543 if (!skipValidation) {
41544 this._validatePropertyOrAttributeName(boundPropertyName, boundProp.sourceSpan, true); 41545 } 41546 41547 securityContexts = calcPossibleSecurityContexts(this._schemaRegistry, elementSelector, boundPropertyName, true); 41548 const nsSeparatorIdx = boundPropertyName.indexOf(':'); 41549 41550 if (nsSeparatorIdx > -1) { 41551 const ns = boundPropertyName.substring(0, nsSeparatorIdx); 41552 const name = boundPropertyName.substring(nsSeparatorIdx + 1); 41553 boundPropertyName = mergeNsAndName(ns, name); 41554 } 41555 41556 bindingType = 1 41557 /* BindingType.Attribute */ 41558 ; 41559 } else if (parts[0] == CLASS_PREFIX) { 41560 boundPropertyName = parts[1]; 41561 bindingType = 2 41562 /* BindingType.Class */ 41563 ; 41564 securityContexts = [SecurityContext.NONE]; 41565 } else if (parts[0] == STYLE_PREFIX) { 41566 unit = parts.length > 2 ? parts[2] : null; 41567 boundPropertyName = parts[1]; 41568 bindingType = 3 41569 /* BindingType.Style */ 41570 ; 41571 securityContexts = [SecurityContext.STYLE]; 41572 } 41573 } // If not a special case, use the full property name 41574 41575 41576 if (boundPropertyName === null) { 41577 const mappedPropName = this._schemaRegistry.getMappedPropName(boundProp.name); 41578 41579 boundPropertyName = mapPropertyName ? mappedPropName : boundProp.name; 41580 securityContexts = calcPossibleSecurityContexts(this._schemaRegistry, elementSelector, mappedPropName, false); 41581 bindingType = 0 41582 /* BindingType.Property */ 41583 ; 41584 41585 if (!skipValidation) { 41586 this._validatePropertyOrAttributeName(mappedPropName, boundProp.sourceSpan, false); 41587 } 41588 } 41589 41590 return new BoundElementProperty(boundPropertyName, bindingType, securityContexts[0], boundProp.expression, unit, boundProp.sourceSpan, boundProp.keySpan, boundProp.valueSpan); 41591 } // TODO: keySpan should be required but was made optional to avoid changing VE parser. 41592 41593 41594 parseEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents, keySpan) { 41595 if (name.length === 0) { 41596 this._reportError(`Event name is missing in binding`, sourceSpan); 41597 } 41598 41599 if (isAnimationLabel(name)) { 41600 name = name.slice(1); 41601 41602 if (keySpan !== undefined) { 41603 keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + 1, keySpan.end.offset)); 41604 } 41605 41606 this._parseAnimationEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetEvents, keySpan); 41607 } else { 41608 this._parseRegularEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents, keySpan); 41609 } 41610 } 41611 41612 calcPossibleSecurityContexts(selector, propName, isAttribute) { 41613 const prop = this._schemaRegistry.getMappedPropName(propName); 41614 41615 return calcPossibleSecurityContexts(this._schemaRegistry, selector, prop, isAttribute); 41616 } 41617 41618 _parseAnimationEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetEvents, keySpan) { 41619 const matches = splitAtPeriod(name, [name, '']); 41620 const eventName = matches[0]; 41621 const phase = matches[1].toLowerCase(); 41622 41623 const ast = this._parseAction(expression, isAssignmentEvent, handlerSpan); 41624 41625 targetEvents.push(new ParsedEvent(eventName, phase, 1 41626 /* ParsedEventType.Animation */ 41627 , ast, sourceSpan, handlerSpan, keySpan)); 41628 41629 if (eventName.length === 0) { 41630 this._reportError(`Animation event name is missing in binding`, sourceSpan); 41631 } 41632 41633 if (phase) { 41634 if (phase !== 'start' && phase !== 'done') { 41635 this._reportError(`The provided animation output phase value "${phase}" for "@${eventName}" is not supported (use start or done)`, sourceSpan); 41636 } 41637 } else { 41638 this._reportError(`The animation trigger output event (@${eventName}) is missing its phase value name (start or done are currently supported)`, sourceSpan); 41639 } 41640 } 41641 41642 _parseRegularEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents, keySpan) { 41643 // long format: 'target: eventName' 41644 const [target, eventName] = splitAtColon(name, [null, name]); 41645 41646 const ast = this._parseAction(expression, isAssignmentEvent, handlerSpan); 41647 41648 targetMatchableAttrs.push([name, ast.source]); 41649 targetEvents.push(new ParsedEvent(eventName, target, 0 41650 /* ParsedEventType.Regular */ 41651 , ast, sourceSpan, handlerSpan, keySpan)); // Don't detect directives for event names for now, 41652 // so don't add the event name to the matchableAttrs 41653 } 41654
41655 _parseAction(value, isAssignmentEvent, sourceSpan) { 41656 const sourceInfo = (sourceSpan && sourceSpan.start || '(unknown').toString(); 41657 const absoluteOffset = sourceSpan && sourceSpan.start ? sourceSpan.start.offset : 0; 41658 41659 try { 41660 const ast = this._exprParser.parseAction(value, isAssignmentEvent, sourceInfo, absoluteOffset, this._interpolationConfig); 41661 41662 if (ast) { 41663 this._reportExpressionParserErrors(ast.errors, sourceSpan); 41664 } 41665 41666 if (!ast || ast.ast instanceof EmptyExpr) { 41667 this._reportError(`Empty expressions are not allowed`, sourceSpan); 41668 41669 return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset); 41670 } 41671 41672 return ast; 41673 } catch (e) { 41674 this._reportError(`${e}`, sourceSpan); 41675 41676 return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset); 41677 } 41678 } 41679 41680 _reportError(message, sourceSpan, level = ParseErrorLevel.ERROR) { 41681 this.errors.push(new ParseError(sourceSpan, message, level)); 41682 } 41683 41684 _reportExpressionParserErrors(errors, sourceSpan) { 41685 for (const error of errors) { 41686 this._reportError(error.message, sourceSpan); 41687 } 41688 } 41689 /** 41690 * @param propName the name of the property / attribute 41691 * @param sourceSpan 41692 * @param isAttr true when binding to an attribute 41693 */ 41694 41695 41696 _validatePropertyOrAttributeName(propName, sourceSpan, isAttr) { 41697 const report = isAttr ? this._schemaRegistry.validateAttribute(propName) : this._schemaRegistry.validateProperty(propName); 41698 41699 if (report.error) { 41700 this._reportError(report.msg, sourceSpan, ParseErrorLevel.ERROR); 41701 } 41702 } 41703 41704} 41705 41706class PipeCollector extends RecursiveAstVisitor { 41707 constructor() { 41708 super(...arguments); 41709 this.pipes = new Map(); 41710 } 41711 41712 visitPipe(ast, context) { 41713 this.pipes.set(ast.name, ast); 41714 ast.exp.visit(this); 41715 this.visitAll(ast.args, context); 41716 return null; 41717 } 41718 41719} 41720 41721function isAnimationLabel(name) { 41722 return name[0] == '@'; 41723} 41724 41725function calcPossibleSecurityContexts(registry, selector, propName, isAttribute) { 41726 const ctxs = []; 41727 CssSelector.parse(selector).forEach(selector => { 41728 const elementNames = selector.element ? [selector.element] : registry.allKnownElementNames(); 41729 const notElementNames = new Set(selector.notSelectors.filter(selector => selector.isElementSelector()).map(selector => selector.element)); 41730 const possibleElementNames = elementNames.filter(elementName => !notElementNames.has(elementName)); 41731 ctxs.push(...possibleElementNames.map(elementName => registry.securityContext(elementName, propName, isAttribute))); 41732 }); 41733 return ctxs.length === 0 ? [SecurityContext.NONE] : Array.from(new Set(ctxs)).sort(); 41734} 41735/** 41736 * Compute a new ParseSourceSpan based off an original `sourceSpan` by using 41737 * absolute offsets from the specified `absoluteSpan`. 41738 * 41739 * @param sourceSpan original source span 41740 * @param absoluteSpan absolute source span to move to 41741 */ 41742 41743 41744function moveParseSourceSpan(sourceSpan, absoluteSpan) { 41745 // The difference of two absolute offsets provide the relative offset 41746 const startDiff = absoluteSpan.start - sourceSpan.start.offset; 41747 const endDiff = absoluteSpan.end - sourceSpan.end.offset; 41748 return new ParseSourceSpan(sourceSpan.start.moveBy(startDiff), sourceSpan.end.moveBy(endDiff), sourceSpan.fullStart.moveBy(startDiff), sourceSpan.details); 41749} 41750/** 41751 * @license 41752 * Copyright Google LLC All Rights Reserved. 41753 * 41754 * Use of this source code is governed by an MIT-style license that can be 41755 * found in the LICENSE file at https://angular.io/license 41756 */ 41757// Some of the code comes from WebComponents.JS 41758// https://github.com/webcomponents/webcomponentsjs/blob/master/src/HTMLImports/path.js 41759 41760 41761function isStyleUrlResolvable(url) { 41762 if (url == null || url.length === 0 || url[0] == '/') return false; 41763 const schemeMatch = url.match(URL_WITH_SCHEMA_REGEXP); 41764 return schemeMatch === null || schemeMatch[1] == 'package' || schemeMatch[1] == 'asset'; 41765} 41766 41767const URL_WITH_SCHEMA_REGEXP = /^([^:/?#]+):/; 41768/** 41769 * @license 41770 * Copyright Google LLC All Rights Reserved. 41771 * 41772 * Use of this source code is governed by an MIT-style license that can be 41773 * found in the LICENSE file at https://angular.io/license 41774 */ 41775 41776const NG_CONTENT_SELECT_ATTR$1 = 'select'; 41777const LINK_ELEMENT = 'link'; 41778const LINK_STYLE_REL_ATTR = 'rel'; 41779const LINK_STYLE_HREF_ATTR = 'href'; 41780const LINK_STYLE_REL_VALUE = 'stylesheet'; 41781const STYLE_ELEMENT = 'style'; 41782const SCRIPT_ELEMENT = 'script'; 41783const NG_NON_BINDABLE_ATTR = 'ngNonBindable'; 41784const NG_PROJECT_AS = 'ngProjectAs'; 41785 41786function preparseElement(ast) { 41787 let selectAttr = null; 41788 let hrefAttr = null; 41789 let relAttr = null; 41790 let nonBindable = false;
41791 let projectAs = ''; 41792 ast.attrs.forEach(attr => { 41793 const lcAttrName = attr.name.toLowerCase(); 41794 41795 if (lcAttrName == NG_CONTENT_SELECT_ATTR$1) { 41796 selectAttr = attr.value; 41797 } else if (lcAttrName == LINK_STYLE_HREF_ATTR) { 41798 hrefAttr = attr.value; 41799 } else if (lcAttrName == LINK_STYLE_REL_ATTR) { 41800 relAttr = attr.value; 41801 } else if (attr.name == NG_NON_BINDABLE_ATTR) { 41802 nonBindable = true; 41803 } else if (attr.name == NG_PROJECT_AS) { 41804 if (attr.value.length > 0) { 41805 projectAs = attr.value; 41806 } 41807 } 41808 }); 41809 selectAttr = normalizeNgContentSelect(selectAttr); 41810 const nodeName = ast.name.toLowerCase(); 41811 let type = PreparsedElementType.OTHER; 41812 41813 if (isNgContent(nodeName)) { 41814 type = PreparsedElementType.NG_CONTENT; 41815 } else if (nodeName == STYLE_ELEMENT) { 41816 type = PreparsedElementType.STYLE; 41817 } else if (nodeName == SCRIPT_ELEMENT) { 41818 type = PreparsedElementType.SCRIPT; 41819 } else if (nodeName == LINK_ELEMENT && relAttr == LINK_STYLE_REL_VALUE) { 41820 type = PreparsedElementType.STYLESHEET; 41821 } 41822 41823 return new PreparsedElement(type, selectAttr, hrefAttr, nonBindable, projectAs); 41824} 41825 41826var PreparsedElementType; 41827 41828(function (PreparsedElementType) { 41829 PreparsedElementType[PreparsedElementType["NG_CONTENT"] = 0] = "NG_CONTENT"; 41830 PreparsedElementType[PreparsedElementType["STYLE"] = 1] = "STYLE"; 41831 PreparsedElementType[PreparsedElementType["STYLESHEET"] = 2] = "STYLESHEET"; 41832 PreparsedElementType[PreparsedElementType["SCRIPT"] = 3] = "SCRIPT"; 41833 PreparsedElementType[PreparsedElementType["OTHER"] = 4] = "OTHER"; 41834})(PreparsedElementType || (PreparsedElementType = {})); 41835 41836class PreparsedElement { 41837 constructor(type, selectAttr, hrefAttr, nonBindable, projectAs) { 41838 this.type = type; 41839 this.selectAttr = selectAttr; 41840 this.hrefAttr = hrefAttr; 41841 this.nonBindable = nonBindable; 41842 this.projectAs = projectAs; 41843 } 41844 41845} 41846 41847function normalizeNgContentSelect(selectAttr) { 41848 if (selectAttr === null || selectAttr.length === 0) { 41849 return '*'; 41850 } 41851 41852 return selectAttr; 41853} 41854/** 41855 * @license 41856 * Copyright Google LLC All Rights Reserved. 41857 * 41858 * Use of this source code is governed by an MIT-style license that can be 41859 * found in the LICENSE file at https://angular.io/license 41860 */ 41861 41862 41863const BIND_NAME_REGEXP = /^(?:(bind-)|(let-)|(ref-|#)|(on-)|(bindon-)|(@))(.*)$/; // Group 1 = "bind-" 41864 41865const KW_BIND_IDX = 1; // Group 2 = "let-" 41866 41867const KW_LET_IDX = 2; // Group 3 = "ref-/#" 41868 41869const KW_REF_IDX = 3; // Group 4 = "on-" 41870 41871const KW_ON_IDX = 4; // Group 5 = "bindon-" 41872 41873const KW_BINDON_IDX = 5; // Group 6 = "@" 41874 41875const KW_AT_IDX = 6; // Group 7 = the identifier after "bind-", "let-", "ref-/#", "on-", "bindon-" or "@" 41876 41877const IDENT_KW_IDX = 7; 41878const BINDING_DELIMS = { 41879 BANANA_BOX: { 41880 start: '[(', 41881 end: ')]' 41882 }, 41883 PROPERTY: { 41884 start: '[', 41885 end: ']' 41886 }, 41887 EVENT: { 41888 start: '(', 41889 end: ')' 41890 } 41891}; 41892const TEMPLATE_ATTR_PREFIX = '*'; 41893 41894function htmlAstToRender3Ast(htmlNodes, bindingParser, options) { 41895 const transformer = new HtmlAstToIvyAst(bindingParser, options); 41896 const ivyNodes = visitAll(transformer, htmlNodes); // Errors might originate in either the binding parser or the html to ivy transformer 41897 41898 const allErrors = bindingParser.errors.concat(transformer.errors); 41899 const result = { 41900 nodes: ivyNodes, 41901 errors: allErrors, 41902 styleUrls: transformer.styleUrls, 41903 styles: transformer.styles, 41904 ngContentSelectors: transformer.ngContentSelectors 41905 }; 41906 41907 if (options.collectCommentNodes) { 41908 result.commentNodes = transformer.commentNodes; 41909 } 41910 41911 return result; 41912} 41913 41914class HtmlAstToIvyAst { 41915 constructor(bindingParser, options) { 41916 this.bindingParser = bindingParser; 41917 this.options = options; 41918 this.errors = []; 41919 this.styles = []; 41920 this.styleUrls = []; 41921 this.ngContentSelectors = []; // This array will be populated if `Render3ParseOptions['collectCommentNodes']` is true 41922 41923 this.commentNodes = []; 41924 this.inI18nBlock = false; 41925 } // HTML visitor 41926 41927 41928 visitElement(element) { 41929 const isI18nRootElement = isI18nRootNode(element.i18n); 41930 41931 if (isI18nRootElement) { 41932 if (this.inI18nBlock) { 41933 this.reportError('Cannot mark an element as translatable inside of a translatable section. Please remove the nested i18n marker.', element.sourceSpan); 41934 } 41935 41936 this.inI18nBlock = true; 41937 } 41938 41939 const preparsedElement = preparseElement(element); 41940 41941 if (preparsedElement.type === PreparsedElementType.SCRIPT) { 41942 return null; 41943 } else if (preparsedElement.type === PreparsedElementType.STYLE) { 41944 const contents = textContents(element); 41945 41946 if (contents !== null) { 41947 this.styles.push(contents); 41948 } 41949 41950 return null; 41951 } else if (preparsedElement.type === PreparsedElementType.STYLESHEET && isStyleUrlResolvable(preparsedElement.hrefAttr)) { 41952 this.styleUrls.push(preparsedElement.hrefAttr); 41953 return null; 41954 } // Whether the element is a `<ng-template>` 41955 41956 41957 const isTemplateElement = isNgTemplate(element.name); 41958 const parsedProperties = []; 41959 const boundEvents = []; 41960 const variables = []; 41961 const references = []; 41962 const attributes = []; 41963 const i18nAttrsMeta = {}; 41964 const templateParsedProperties = []; 41965 const templateVariables = []; // Whether the element has any *-attribute 41966 41967 let elementHasInlineTemplate = false;
41968 41969 for (const attribute of element.attrs) { 41970 let hasBinding = false; 41971 const normalizedName = normalizeAttributeName(attribute.name); // `*attr` defines template bindings 41972 41973 let isTemplateBinding = false; 41974 41975 if (attribute.i18n) { 41976 i18nAttrsMeta[attribute.name] = attribute.i18n; 41977 } 41978 41979 if (normalizedName.startsWith(TEMPLATE_ATTR_PREFIX)) { 41980 // *-attributes 41981 if (elementHasInlineTemplate) { 41982 this.reportError(`Can't have multiple template bindings on one element. Use only one attribute prefixed with *`, attribute.sourceSpan); 41983 } 41984 41985 isTemplateBinding = true; 41986 elementHasInlineTemplate = true; 41987 const templateValue = attribute.value; 41988 const templateKey = normalizedName.substring(TEMPLATE_ATTR_PREFIX.length); 41989 const parsedVariables = []; 41990 const absoluteValueOffset = attribute.valueSpan ? attribute.valueSpan.start.offset : // If there is no value span the attribute does not have a value, like `attr` in 41991 //`<div attr></div>`. In this case, point to one character beyond the last character of 41992 // the attribute name. 41993 attribute.sourceSpan.start.offset + attribute.name.length; 41994 this.bindingParser.parseInlineTemplateBinding(templateKey, templateValue, attribute.sourceSpan, absoluteValueOffset, [], templateParsedProperties, parsedVariables, true 41995 /* isIvyAst */ 41996 ); 41997 templateVariables.push(...parsedVariables.map(v => new Variable(v.name, v.value, v.sourceSpan, v.keySpan, v.valueSpan))); 41998 } else { 41999 // Check for variables, events, property bindings, interpolation 42000 hasBinding = this.parseAttribute(isTemplateElement, attribute, [], parsedProperties, boundEvents, variables, references); 42001 } 42002 42003 if (!hasBinding && !isTemplateBinding) { 42004 // don't include the bindings as attributes as well in the AST 42005 attributes.push(this.visitAttribute(attribute)); 42006 } 42007 } 42008 42009 const children = visitAll(preparsedElement.nonBindable ? NON_BINDABLE_VISITOR : this, element.children); 42010 let parsedElement; 42011 42012 if (preparsedElement.type === PreparsedElementType.NG_CONTENT) { 42013 // `<ng-content>` 42014 if (element.children && !element.children.every(node => isEmptyTextNode(node) || isCommentNode(node))) { 42015 this.reportError(`<ng-content> element cannot have content.`, element.sourceSpan); 42016 } 42017 42018 const selector = preparsedElement.selectAttr; 42019 const attrs = element.attrs.map(attr => this.visitAttribute(attr)); 42020 parsedElement = new Content(selector, attrs, element.sourceSpan, element.i18n); 42021 this.ngContentSelectors.push(selector); 42022 } else if (isTemplateElement) { 42023 // `<ng-template>` 42024 const attrs = this.extractAttributes(element.name, parsedProperties, i18nAttrsMeta); 42025 parsedElement = new Template(element.name, attributes, attrs.bound, boundEvents, [ 42026 /* no template attributes */ 42027 ], children, references, variables, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n); 42028 } else { 42029 const attrs = this.extractAttributes(element.name, parsedProperties, i18nAttrsMeta); 42030 parsedElement = new Element$1(element.name, attributes, attrs.bound, boundEvents, children, references, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n); 42031 } 42032 42033 if (elementHasInlineTemplate) { 42034 // If this node is an inline-template (e.g. has *ngFor) then we need to create a template
42035 // node that contains this node. 42036 // Moreover, if the node is an element, then we need to hoist its attributes to the template 42037 // node for matching against content projection selectors. 42038 const attrs = this.extractAttributes('ng-template', templateParsedProperties, i18nAttrsMeta); 42039 const templateAttrs = []; 42040 attrs.literal.forEach(attr => templateAttrs.push(attr)); 42041 attrs.bound.forEach(attr => templateAttrs.push(attr)); 42042 const hoistedAttrs = parsedElement instanceof Element$1 ? { 42043 attributes: parsedElement.attributes, 42044 inputs: parsedElement.inputs, 42045 outputs: parsedElement.outputs 42046 } : { 42047 attributes: [], 42048 inputs: [], 42049 outputs: [] 42050 }; // For <ng-template>s with structural directives on them, avoid passing i18n information to 42051 // the wrapping template to prevent unnecessary i18n instructions from being generated. The 42052 // necessary i18n meta information will be extracted from child elements. 42053 42054 const i18n = isTemplateElement && isI18nRootElement ? undefined : element.i18n; 42055 const name = parsedElement instanceof Template ? null : parsedElement.name; 42056 parsedElement = new Template(name, hoistedAttrs.attributes, hoistedAttrs.inputs, hoistedAttrs.outputs, templateAttrs, [parsedElement], [ 42057 /* no references */ 42058 ], templateVariables, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, i18n); 42059 } 42060 42061 if (isI18nRootElement) { 42062 this.inI18nBlock = false; 42063 } 42064 42065 return parsedElement; 42066 } 42067 42068 visitAttribute(attribute) { 42069 return new TextAttribute(attribute.name, attribute.value, attribute.sourceSpan, attribute.keySpan, attribute.valueSpan, attribute.i18n); 42070 } 42071 42072 visitText(text) { 42073 return this._visitTextWithInterpolation(text.value, text.sourceSpan, text.tokens, text.i18n); 42074 } 42075 42076 visitExpansion(expansion) { 42077 if (!expansion.i18n) { 42078 // do not generate Icu in case it was created 42079 // outside of i18n block in a template 42080 return null; 42081 } 42082 42083 if (!isI18nRootNode(expansion.i18n)) { 42084 throw new Error(`Invalid type "${expansion.i18n.constructor}" for "i18n" property of ${expansion.sourceSpan.toString()}. Expected a "Message"`); 42085 } 42086 42087 const message = expansion.i18n; 42088 const vars = {}; 42089 const placeholders = {}; // extract VARs from ICUs - we process them separately while 42090 // assembling resulting message via goog.getMsg function, since 42091 // we need to pass them to top-level goog.getMsg call 42092 42093 Object.keys(message.placeholders).forEach(key => { 42094 const value = message.placeholders[key]; 42095 42096 if (key.startsWith(I18N_ICU_VAR_PREFIX)) { 42097 // Currently when the `plural` or `select` keywords in an ICU contain trailing spaces (e.g. 42098 // `{count, select , ...}`), these spaces are also included into the key names in ICU vars 42099 // (e.g. "VAR_SELECT "). These trailing spaces are not desirable, since they will later be 42100 // converted into `_` symbols while normalizing placeholder names, which might lead to 42101 // mismatches at runtime (i.e. placeholder will not be replaced with the correct value). 42102 const formattedKey = key.trim(); 42103 const ast = this.bindingParser.parseInterpolationExpression(value.text, value.sourceSpan); 42104 vars[formattedKey] = new BoundText(ast, value.sourceSpan); 42105 } else { 42106 placeholders[key] = this._visitTextWithInterpolation(value.text, value.sourceSpan, null); 42107 } 42108 }); 42109 return new Icu$1(vars, placeholders, expansion.sourceSpan, message); 42110 } 42111 42112 visitExpansionCase(expansionCase) { 42113 return null; 42114 } 42115 42116 visitComment(comment) { 42117 if (this.options.collectCommentNodes) { 42118 this.commentNodes.push(new Comment$1(comment.value || '', comment.sourceSpan)); 42119 } 42120 42121 return null; 42122 } // convert view engine `ParsedProperty` to a format suitable for IVY 42123 42124 42125 extractAttributes(elementName, properties, i18nPropsMeta) { 42126 const bound = []; 42127 const literal = []; 42128 properties.forEach(prop => { 42129 const i18n = i18nPropsMeta[prop.name]; 42130 42131 if (prop.isLiteral) { 42132 literal.push(new TextAttribute(prop.name, prop.expression.source || '', prop.sourceSpan, prop.keySpan, prop.valueSpan, i18n)); 42133 } else { 42134 // Note that validation is skipped and property mapping is disabled 42135 // due to the fact that we need to make sure a given prop is not an 42136 // input of a directive and directive matching happens at runtime. 42137 const bep = this.bindingParser.createBoundElementProperty(elementName, prop, 42138 /* skipValidation */ 42139 true, 42140 /* mapPropertyName */ 42141 false); 42142 bound.push(BoundAttribute.fromBoundElementProperty(bep, i18n)); 42143 } 42144 }); 42145 return { 42146 bound, 42147 literal 42148 }; 42149 } 42150 42151 parseAttribute(isTemplateElement, attribute, matchableAttributes, parsedProperties, boundEvents, variables, references) { 42152 const name = normalizeAttributeName(attribute.name); 42153 const value = attribute.value; 42154 const srcSpan = attribute.sourceSpan; 42155 const absoluteOffset = attribute.valueSpan ? attribute.valueSpan.start.offset : srcSpan.start.offset; 42156 42157 function createKeySpan(srcSpan, prefix, identifier) { 42158 // We need to adjust the start location for the keySpan to account for the removed 'data-' 42159 // prefix from `normalizeAttributeName`. 42160 const normalizationAdjustment = attribute.name.length - name.length;
42161 const keySpanStart = srcSpan.start.moveBy(prefix.length + normalizationAdjustment); 42162 const keySpanEnd = keySpanStart.moveBy(identifier.length); 42163 return new ParseSourceSpan(keySpanStart, keySpanEnd, keySpanStart, identifier); 42164 } 42165 42166 const bindParts = name.match(BIND_NAME_REGEXP); 42167 42168 if (bindParts) { 42169 if (bindParts[KW_BIND_IDX] != null) { 42170 const identifier = bindParts[IDENT_KW_IDX]; 42171 const keySpan = createKeySpan(srcSpan, bindParts[KW_BIND_IDX], identifier); 42172 this.bindingParser.parsePropertyBinding(identifier, value, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan); 42173 } else if (bindParts[KW_LET_IDX]) { 42174 if (isTemplateElement) { 42175 const identifier = bindParts[IDENT_KW_IDX]; 42176 const keySpan = createKeySpan(srcSpan, bindParts[KW_LET_IDX], identifier); 42177 this.parseVariable(identifier, value, srcSpan, keySpan, attribute.valueSpan, variables); 42178 } else { 42179 this.reportError(`"let-" is only supported on ng-template elements.`, srcSpan); 42180 } 42181 } else if (bindParts[KW_REF_IDX]) { 42182 const identifier = bindParts[IDENT_KW_IDX]; 42183 const keySpan = createKeySpan(srcSpan, bindParts[KW_REF_IDX], identifier); 42184 this.parseReference(identifier, value, srcSpan, keySpan, attribute.valueSpan, references); 42185 } else if (bindParts[KW_ON_IDX]) { 42186 const events = []; 42187 const identifier = bindParts[IDENT_KW_IDX]; 42188 const keySpan = createKeySpan(srcSpan, bindParts[KW_ON_IDX], identifier); 42189 this.bindingParser.parseEvent(identifier, value, 42190 /* isAssignmentEvent */ 42191 false, srcSpan, attribute.valueSpan || srcSpan, matchableAttributes, events, keySpan); 42192 addEvents(events, boundEvents); 42193 } else if (bindParts[KW_BINDON_IDX]) { 42194 const identifier = bindParts[IDENT_KW_IDX]; 42195 const keySpan = createKeySpan(srcSpan, bindParts[KW_BINDON_IDX], identifier); 42196 this.bindingParser.parsePropertyBinding(identifier, value, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan); 42197 this.parseAssignmentEvent(identifier, value, srcSpan, attribute.valueSpan, matchableAttributes, boundEvents, keySpan); 42198 } else if (bindParts[KW_AT_IDX]) { 42199 const keySpan = createKeySpan(srcSpan, '', name); 42200 this.bindingParser.parseLiteralAttr(name, value, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan); 42201 } 42202 42203 return true; 42204 } // We didn't see a kw-prefixed property binding, but we have not yet checked 42205 // for the []/()/[()] syntax. 42206 42207 42208 let delims = null; 42209 42210 if (name.startsWith(BINDING_DELIMS.BANANA_BOX.start)) { 42211 delims = BINDING_DELIMS.BANANA_BOX; 42212 } else if (name.startsWith(BINDING_DELIMS.PROPERTY.start)) { 42213 delims = BINDING_DELIMS.PROPERTY; 42214 } else if (name.startsWith(BINDING_DELIMS.EVENT.start)) { 42215 delims = BINDING_DELIMS.EVENT; 42216 } 42217 42218 if (delims !== null && // NOTE: older versions of the parser would match a start/end delimited 42219 // binding iff the property name was terminated by the ending delimiter 42220 // and the identifier in the binding was non-empty. 42221 // TODO(ayazhafiz): update this to handle malformed bindings. 42222 name.endsWith(delims.end) && name.length > delims.start.length + delims.end.length) { 42223 const identifier = name.substring(delims.start.length, name.length - delims.end.length); 42224 const keySpan = createKeySpan(srcSpan, delims.start, identifier); 42225 42226 if (delims.start === BINDING_DELIMS.BANANA_BOX.start) { 42227 this.bindingParser.parsePropertyBinding(identifier, value, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan); 42228 this.parseAssignmentEvent(identifier, value, srcSpan, attribute.valueSpan, matchableAttributes, boundEvents, keySpan); 42229 } else if (delims.start === BINDING_DELIMS.PROPERTY.start) { 42230 this.bindingParser.parsePropertyBinding(identifier, value, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan); 42231 } else { 42232 const events = []; 42233 this.bindingParser.parseEvent(identifier, value, 42234 /* isAssignmentEvent */ 42235 false, srcSpan, attribute.valueSpan || srcSpan, matchableAttributes, events, keySpan); 42236 addEvents(events, boundEvents); 42237 } 42238 42239 return true; 42240 } // No explicit binding found. 42241 42242
42243 const keySpan = createKeySpan(srcSpan, '' 42244 /* prefix */ 42245 , name); 42246 const hasBinding = this.bindingParser.parsePropertyInterpolation(name, value, srcSpan, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan, attribute.valueTokens ?? null); 42247 return hasBinding; 42248 } 42249 42250 _visitTextWithInterpolation(value, sourceSpan, interpolatedTokens, i18n) { 42251 const valueNoNgsp = replaceNgsp(value); 42252 const expr = this.bindingParser.parseInterpolation(valueNoNgsp, sourceSpan, interpolatedTokens); 42253 return expr ? new BoundText(expr, sourceSpan, i18n) : new Text$3(valueNoNgsp, sourceSpan); 42254 } 42255 42256 parseVariable(identifier, value, sourceSpan, keySpan, valueSpan, variables) { 42257 if (identifier.indexOf('-') > -1) { 42258 this.reportError(`"-" is not allowed in variable names`, sourceSpan); 42259 } else if (identifier.length === 0) { 42260 this.reportError(`Variable does not have a name`, sourceSpan); 42261 } 42262 42263 variables.push(new Variable(identifier, value, sourceSpan, keySpan, valueSpan)); 42264 } 42265 42266 parseReference(identifier, value, sourceSpan, keySpan, valueSpan, references) { 42267 if (identifier.indexOf('-') > -1) { 42268 this.reportError(`"-" is not allowed in reference names`, sourceSpan); 42269 } else if (identifier.length === 0) { 42270 this.reportError(`Reference does not have a name`, sourceSpan); 42271 } else if (references.some(reference => reference.name === identifier)) { 42272 this.reportError(`Reference "#${identifier}" is defined more than once`, sourceSpan); 42273 } 42274 42275 references.push(new Reference(identifier, value, sourceSpan, keySpan, valueSpan)); 42276 } 42277 42278 parseAssignmentEvent(name, expression, sourceSpan, valueSpan, targetMatchableAttrs, boundEvents, keySpan) { 42279 const events = []; 42280 this.bindingParser.parseEvent(`${name}Change`, `${expression} =$event`, 42281 /* isAssignmentEvent */ 42282 true, sourceSpan, valueSpan || sourceSpan, targetMatchableAttrs, events, keySpan); 42283 addEvents(events, boundEvents); 42284 } 42285 42286 reportError(message, sourceSpan, level = ParseErrorLevel.ERROR) { 42287 this.errors.push(new ParseError(sourceSpan, message, level)); 42288 } 42289 42290} 42291 42292class NonBindableVisitor { 42293 visitElement(ast) { 42294 const preparsedElement = preparseElement(ast); 42295 42296 if (preparsedElement.type === PreparsedElementType.SCRIPT || preparsedElement.type === PreparsedElementType.STYLE || preparsedElement.type === PreparsedElementType.STYLESHEET) { 42297 // Skipping <script> for security reasons 42298 // Skipping <style> and stylesheets as we already processed them 42299 // in the StyleCompiler 42300 return null; 42301 } 42302 42303 const children = visitAll(this, ast.children, null); 42304 return new Element$1(ast.name, visitAll(this, ast.attrs), 42305 /* inputs */ 42306 [], 42307 /* outputs */ 42308 [], children, 42309 /* references */ 42310 [], ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan); 42311 } 42312 42313 visitComment(comment) { 42314 return null; 42315 } 42316 42317 visitAttribute(attribute) { 42318 return new TextAttribute(attribute.name, attribute.value, attribute.sourceSpan, attribute.keySpan, attribute.valueSpan, attribute.i18n); 42319 } 42320 42321 visitText(text) { 42322 return new Text$3(text.value, text.sourceSpan); 42323 } 42324 42325 visitExpansion(expansion) { 42326 return null; 42327 } 42328 42329 visitExpansionCase(expansionCase) { 42330 return null; 42331 } 42332 42333} 42334 42335const NON_BINDABLE_VISITOR = new NonBindableVisitor(); 42336 42337function normalizeAttributeName(attrName) { 42338 return /^data-/i.test(attrName) ? attrName.substring(5) : attrName; 42339} 42340 42341function addEvents(events, boundEvents) { 42342 boundEvents.push(...events.map(e => BoundEvent.fromParsedEvent(e))); 42343} 42344 42345function isEmptyTextNode(node) { 42346 return node instanceof Text && node.value.trim().length == 0; 42347} 42348 42349function isCommentNode(node) { 42350 return node instanceof Comment; 42351} 42352 42353function textContents(node) { 42354 if (node.children.length !== 1 || !(node.children[0] instanceof Text)) { 42355 return null; 42356 } else { 42357 return node.children[0].value; 42358 } 42359} 42360/** 42361 * @license 42362 * Copyright Google LLC All Rights Reserved. 42363 * 42364 * Use of this source code is governed by an MIT-style license that can be 42365 * found in the LICENSE file at https://angular.io/license 42366 */ 42367 42368 42369var TagType; 42370 42371(function (TagType) { 42372 TagType[TagType["ELEMENT"] = 0] = "ELEMENT"; 42373 TagType[TagType["TEMPLATE"] = 1] = "TEMPLATE"; 42374})(TagType || (TagType = {})); 42375/** 42376 * Generates an object that is used as a shared state between parent and all child contexts. 42377 */ 42378 42379 42380function setupRegistry() { 42381 return { 42382 getUniqueId: getSeqNumberGenerator(), 42383 icus: new Map() 42384 }; 42385} 42386/** 42387 * I18nContext is a helper class which keeps track of all i18n-related as
42387pects 42388 * (accumulates placeholders, bindings, etc) between i18nStart and i18nEnd instructions. 42389 * 42390 * When we enter a nested template, the top-level context is being passed down 42391 * to the nested component, which uses this context to generate a child instance 42392 * of I18nContext class (to handle nested template) and at the end, reconciles it back 42393 * with the parent context. 42394 * 42395 * @param index Instruction index of i18nStart, which initiates this context 42396 * @param ref Reference to a translation const that represents the content if thus context 42397 * @param level Nesting level defined for child contexts 42398 * @param templateIndex Instruction index of a template which this context belongs to 42399 * @param meta Meta information (id, meaning, description, etc) associated with this context 42400 */ 42401 42402 42403class I18nContext { 42404 constructor(index, ref, level = 0, templateIndex = null, meta, registry) { 42405 this.index = index; 42406 this.ref = ref; 42407 this.level = level; 42408 this.templateIndex = templateIndex; 42409 this.meta = meta; 42410 this.registry = registry; 42411 this.bindings = new Set(); 42412 this.placeholders = new Map(); 42413 this.isEmitted = false; 42414 this._unresolvedCtxCount = 0; 42415 this._registry = registry || setupRegistry(); 42416 this.id = this._registry.getUniqueId(); 42417 } 42418 42419 appendTag(type, node, index, closed) { 42420 if (node.isVoid && closed) { 42421 return; // ignore "close" for void tags 42422 } 42423 42424 const ph = node.isVoid || !closed ? node.startName : node.closeName; 42425 const content = { 42426 type, 42427 index, 42428 ctx: this.id, 42429 isVoid: node.isVoid, 42430 closed 42431 }; 42432 updatePlaceholderMap(this.placeholders, ph, content); 42433 } 42434 42435 get icus() { 42436 return this._registry.icus; 42437 } 42438 42439 get isRoot() { 42440 return this.level === 0; 42441 } 42442 42443 get isResolved() { 42444 return this._unresolvedCtxCount === 0; 42445 } 42446 42447 getSerializedPlaceholders() { 42448 const result = new Map(); 42449 this.placeholders.forEach((values, key) => result.set(key, values.map(serializePlaceholderValue))); 42450 return result; 42451 } // public API to accumulate i18n-related content 42452 42453 42454 appendBinding(binding) { 42455 this.bindings.add(binding); 42456 } 42457 42458 appendIcu(name, ref) { 42459 updatePlaceholderMap(this._registry.icus, name, ref); 42460 } 42461 42462 appendBoundText(node) { 42463 const phs = assembleBoundTextPlaceholders(node, this.bindings.size, this.id); 42464 phs.forEach((values, key) => updatePlaceholderMap(this.placeholders, key, ...values)); 42465 } 42466 42467 appendTemplate(node, index) { 42468 // add open and close tags at the same time, 42469 // since we process nested templates separately 42470 this.appendTag(TagType.TEMPLATE, node, index, false); 42471 this.appendTag(TagType.TEMPLATE, node, index, true); 42472 this._unresolvedCtxCount++; 42473 } 42474 42475 appendElement(node, index, closed) { 42476 this.appendTag(TagType.ELEMENT, node, index, closed); 42477 } 42478 42479 appendProjection(node, index) { 42480 // Add open and close tags at the same time, since `<ng-content>` has no content, 42481 // so when we come across `<ng-content>` we can register both open and close tags. 42482 // Note: runtime i18n logic doesn't distinguish `<ng-content>` tag placeholders and 42483 // regular element tag placeholders, so we generate element placeholders for both types. 42484 this.appendTag(TagType.ELEMENT, node, index, false); 42485 this.appendTag(TagType.ELEMENT, node, index, true); 42486 } 42487 /** 42488 * Generates an instance of a child context based on the root one, 42489 * when we enter a nested template within I18n section. 42490 * 42491 * @param index Instruction index of corresponding i18nStart, which initiates this context 42492 * @param templateIndex Instruction index of a template which this context belongs to 42493 * @param meta Meta information (id, meaning, description, etc) associated with this context 42494 * 42495 * @returns I18nContext instance 42496 */ 42497 42498 42499 forkChildContext(index, templateIndex, meta) { 42500 return new I18nContext(index, this.ref, this.level + 1, templateIndex, meta, this._registry); 42501 } 42502 /** 42503 * Reconciles child context into parent one once the end of the i18n block is reached (i18nEnd). 42504 * 42505 * @param context Child I18nContext instance to be reconciled with parent context. 42506 */ 42507 42508 42509 reconcileChildContext(context) { 42510 // set the right context id for open and close 42511 // template tags, so we can use it as sub-block ids 42512 ['start', 'close'].forEach(op => {
42513 const key = context.meta[`${op}Name`]; 42514 const phs = this.placeholders.get(key) || []; 42515 const tag = phs.find(findTemplateFn(this.id, context.templateIndex)); 42516 42517 if (tag) { 42518 tag.ctx = context.id; 42519 } 42520 }); // reconcile placeholders 42521 42522 const childPhs = context.placeholders; 42523 childPhs.forEach((values, key) => { 42524 const phs = this.placeholders.get(key); 42525 42526 if (!phs) { 42527 this.placeholders.set(key, values); 42528 return; 42529 } // try to find matching template... 42530 42531 42532 const tmplIdx = phs.findIndex(findTemplateFn(context.id, context.templateIndex)); 42533 42534 if (tmplIdx >= 0) { 42535 // ... if found - replace it with nested template content 42536 const isCloseTag = key.startsWith('CLOSE'); 42537 const isTemplateTag = key.endsWith('NG-TEMPLATE'); 42538 42539 if (isTemplateTag) { 42540 // current template's content is placed before or after 42541 // parent template tag, depending on the open/close attribute 42542 phs.splice(tmplIdx + (isCloseTag ? 0 : 1), 0, ...values); 42543 } else { 42544 const idx = isCloseTag ? values.length - 1 : 0; 42545 values[idx].tmpl = phs[tmplIdx]; 42546 phs.splice(tmplIdx, 1, ...values); 42547 } 42548 } else { 42549 // ... otherwise just append content to placeholder value 42550 phs.push(...values); 42551 } 42552 42553 this.placeholders.set(key, phs); 42554 }); 42555 this._unresolvedCtxCount--; 42556 } 42557 42558} // 42559// Helper methods 42560// 42561 42562 42563function wrap(symbol, index, contextId, closed) { 42564 const state = closed ? '/' : ''; 42565 return wrapI18nPlaceholder(`${state}${symbol}${index}`, contextId); 42566} 42567 42568function wrapTag(symbol, { 42569 index, 42570 ctx, 42571 isVoid 42572}, closed) { 42573 return isVoid ? wrap(symbol, index, ctx) + wrap(symbol, index, ctx, true) : wrap(symbol, index, ctx, closed); 42574} 42575 42576function findTemplateFn(ctx, templateIndex) { 42577 return token => typeof token === 'object' && token.type === TagType.TEMPLATE && token.index === templateIndex && token.ctx === ctx; 42578} 42579 42580function serializePlaceholderValue(value) { 42581 const element = (data, closed) => wrapTag('#', data, closed); 42582 42583 const template = (data, closed) => wrapTag('*', data, closed); 42584 42585 const projection = (data, closed) => wrapTag('!', data, closed); 42586 42587 switch (value.type) { 42588 case TagType.ELEMENT: 42589 // close element tag 42590 if (value.closed) { 42591 return element(value, true) + (value.tmpl ? template(value.tmpl, true) : ''); 42592 } // open element tag that also initiates a template 42593 42594 42595 if (value.tmpl) { 42596 return template(value.tmpl) + element(value) + (value.isVoid ? template(value.tmpl, true) : ''); 42597 } 42598 42599 return element(value); 42600 42601 case TagType.TEMPLATE: 42602 return template(value, value.closed); 42603 42604 default: 42605 return value; 42606 } 42607} 42608/** 42609 * @license 42610 * Copyright Google LLC All Rights Reserved. 42611 * 42612 * Use of this source code is governed by an MIT-style license that can be 42613 * found in the LICENSE file at https://angular.io/license 42614 */ 42615 42616 42617class IcuSerializerVisitor { 42618 visitText(text) { 42619 return text.value; 42620 } 42621 42622 visitContainer(container) { 42623 return container.children.map(child => child.visit(this)).join(''); 42624 } 42625 42626 visitIcu(icu) { 42627 const strCases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`); 42628 const result = `{${icu.expressionPlaceholder}, ${icu.type}, ${strCases.join(' ')}}`; 42629 return result; 42630 } 42631 42632 visitTagPlaceholder(ph) { 42633 return ph.isVoid ? this.formatPh(ph.startName) : `${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${this.formatPh(ph.closeName)}`; 42634 } 42635 42636 visitPlaceholder(ph) { 42637 return this.formatPh(ph.name); 42638 } 42639 42640 visitIcuPlaceholder(ph, context) { 42641 return this.formatPh(ph.name); 42642 } 42643 42644 formatPh(value) { 42645 return `{${formatI18nPlaceholderName(value, 42646 /* useCamelCase */ 42647 false)}}`; 42648 } 42649 42650} 42651 42652const serializer = new IcuSerializerVisitor(); 42653 42654function serializeIcuNode(icu) { 42655 return icu.visit(serializer); 42656} 42657/** 42658 * @license 42659 * Copyright Google LLC All Rights Reserved. 42660 * 42661 * Use of this source code is governed by an MIT-style license that can be 42662 * found in the LICENSE file at https://angular.io/license 42663 */ 42664 42665 42666const TAG_TO_PLACEHOLDER_NAMES = { 42667 'A': 'LINK', 42668 'B': 'BOLD_TEXT', 42669 'BR': 'LINE_BREAK', 42670 'EM': 'EMPHASISED_TEXT', 42671 'H1': 'HEADING_LEVEL1', 42672 'H2': 'HEADING_LEVEL2', 42673 'H3': 'HEADING_LEVEL3', 42674 'H4': 'HEADING_LEVEL4', 42675 'H5': 'HEADING_LEVEL5', 42676 'H6': 'HEADING_LEVEL6', 42677 'HR': 'HORIZONTAL_RULE', 42678 'I': 'ITALIC_TEXT', 42679 'LI': 'LIST_ITEM', 42680 'LINK': 'MEDIA_LINK', 42681 'OL': 'ORDERED_LIST', 42682 'P': 'PARAGRAPH', 42683 'Q': 'QUOTATION', 42684 'S': 'STRIKETHROUGH_TEXT', 42685 'SMALL': 'SMALL_TEXT', 42686 'SUB': 'SUBSTRIPT', 42687 'SUP': 'SUPERSCRIPT', 42688 'TBODY': 'TABLE_BODY', 42689 'TD': 'TABLE_CELL', 42690 'TFOOT': 'TABLE_FOOTER', 42691 'TH': 'TABLE_HEADER_CELL', 42692 'THEAD': 'TABLE_HEADER', 42693 'TR': 'TABLE_ROW', 42694 'TT': 'MONOSPACED_TEXT', 42695 'U': 'UNDERLINED_TEXT', 42696 'UL': 'UNORDERED_LIST' 42697}; 42698/**
42699 * Creates unique names for placeholder with different content. 42700 * 42701 * Returns the same placeholder name when the content is identical. 42702 */ 42703 42704class PlaceholderRegistry { 42705 constructor() { 42706 // Count the occurrence of the base name top generate a unique name 42707 this._placeHolderNameCounts = {}; // Maps signature to placeholder names 42708 42709 this._signatureToName = {}; 42710 } 42711 42712 getStartTagPlaceholderName(tag, attrs, isVoid) { 42713 const signature = this._hashTag(tag, attrs, isVoid); 42714 42715 if (this._signatureToName[signature]) { 42716 return this._signatureToName[signature]; 42717 } 42718 42719 const upperTag = tag.toUpperCase(); 42720 const baseName = TAG_TO_PLACEHOLDER_NAMES[upperTag] || `TAG_${upperTag}`; 42721 42722 const name = this._generateUniqueName(isVoid ? baseName : `START_${baseName}`); 42723 42724 this._signatureToName[signature] = name; 42725 return name; 42726 } 42727 42728 getCloseTagPlaceholderName(tag) { 42729 const signature = this._hashClosingTag(tag); 42730 42731 if (this._signatureToName[signature]) { 42732 return this._signatureToName[signature]; 42733 } 42734 42735 const upperTag = tag.toUpperCase(); 42736 const baseName = TAG_TO_PLACEHOLDER_NAMES[upperTag] || `TAG_${upperTag}`; 42737 42738 const name = this._generateUniqueName(`CLOSE_${baseName}`); 42739 42740 this._signatureToName[signature] = name; 42741 return name; 42742 } 42743 42744 getPlaceholderName(name, content) { 42745 const upperName = name.toUpperCase(); 42746 const signature = `PH: ${upperName}=${content}`; 42747 42748 if (this._signatureToName[signature]) { 42749 return this._signatureToName[signature]; 42750 } 42751 42752 const uniqueName = this._generateUniqueName(upperName); 42753 42754 this._signatureToName[signature] = uniqueName; 42755 return uniqueName; 42756 } 42757 42758 getUniquePlaceholder(name) { 42759 return this._generateUniqueName(name.toUpperCase()); 42760 } // Generate a hash for a tag - does not take attribute order into account 42761 42762 42763 _hashTag(tag, attrs, isVoid) { 42764 const start = `<${tag}`; 42765 const strAttrs = Object.keys(attrs).sort().map(name => ` ${name}=${attrs[name]}`).join(''); 42766 const end = isVoid ? '/>' : `></${tag}>`; 42767 return start + strAttrs + end; 42768 } 42769 42770 _hashClosingTag(tag) { 42771 return this._hashTag(`/${tag}`, {}, false); 42772 } 42773 42774 _generateUniqueName(base) { 42775 const seen = this._placeHolderNameCounts.hasOwnProperty(base); 42776 42777 if (!seen) { 42778 this._placeHolderNameCounts[base] = 1; 42779 return base; 42780 } 42781 42782 const id = this._placeHolderNameCounts[base]; 42783 this._placeHolderNameCounts[base] = id + 1; 42784 return `${base}_${id}`; 42785 } 42786 42787} 42788/** 42789 * @license 42790 * Copyright Google LLC All Rights Reserved. 42791 * 42792 * Use of this source code is governed by an MIT-style license that can be 42793 * found in the LICENSE file at https://angular.io/license 42794 */ 42795 42796 42797const _expParser = new Parser$1(new Lexer()); 42798/** 42799 * Returns a function converting html nodes to an i18n Message given an interpolationConfig 42800 */ 42801 42802 42803function createI18nMessageFactory(interpolationConfig) { 42804 const visitor = new _I18nVisitor(_expParser, interpolationConfig); 42805 return (nodes, meaning, description, customId, visitNodeFn) => visitor.toI18nMessage(nodes, meaning, description, customId, visitNodeFn); 42806} 42807 42808function noopVisitNodeFn(_html, i18n) { 42809 return i18n; 42810} 42811 42812class _I18nVisitor { 42813 constructor(_expressionParser, _interpolationConfig) { 42814 this._expressionParser = _expressionParser; 42815 this._interpolationConfig = _interpolationConfig; 42816 } 42817 42818 toI18nMessage(nodes, meaning = '', description = '', customId = '', visitNodeFn) { 42819 const context = { 42820 isIcu: nodes.length == 1 && nodes[0] instanceof Expansion, 42821 icuDepth: 0, 42822 placeholderRegistry: new PlaceholderRegistry(), 42823 placeholderToContent: {}, 42824 placeholderToMessage: {}, 42825 visitNodeFn: visitNodeFn || noopVisitNodeFn 42826 }; 42827 const i18nodes = visitAll(this, nodes, context); 42828 return new Message(i18nodes, context.placeholderToContent, context.placeholderToMessage, meaning, description, customId); 42829 } 42830 42831 visitElement(el, context) { 42832 const children = visitAll(this, el.children, context); 42833 const attrs = {}; 42834 el.attrs.forEach(attr => { 42835 // Do not visit the attributes, translatable ones are top-level ASTs 42836 attrs[attr.name] = attr.value; 42837 }); 42838 const isVoid = getHtmlTagDefinition(el.name).isVoid; 42839 const startPhName = context.placeholderRegistry.getStartTagPlaceholderName(el.name, attrs, isVoid); 42840 context.placeholderToContent[startPhName] = { 42841 text: el.startSourceSpan.toString(), 42842 sourceSpan: el.startSourceSpan 42843 };
42844 let closePhName = ''; 42845 42846 if (!isVoid) { 42847 closePhName = context.placeholderRegistry.getCloseTagPlaceholderName(el.name); 42848 context.placeholderToContent[closePhName] = { 42849 text: `</${el.name}>`, 42850 sourceSpan: el.endSourceSpan ?? el.sourceSpan 42851 }; 42852 } 42853 42854 const node = new TagPlaceholder(el.name, attrs, startPhName, closePhName, children, isVoid, el.sourceSpan, el.startSourceSpan, el.endSourceSpan); 42855 return context.visitNodeFn(el, node); 42856 } 42857 42858 visitAttribute(attribute, context) { 42859 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); 42860 return context.visitNodeFn(attribute, node); 42861 } 42862 42863 visitText(text, context) { 42864 const node = text.tokens.length === 1 ? new Text$2(text.value, text.sourceSpan) : this._visitTextWithInterpolation(text.tokens, text.sourceSpan, context, text.i18n); 42865 return context.visitNodeFn(text, node); 42866 } 42867 42868 visitComment(comment, context) { 42869 return null; 42870 } 42871 42872 visitExpansion(icu, context) { 42873 context.icuDepth++; 42874 const i18nIcuCases = {}; 42875 const i18nIcu = new Icu(icu.switchValue, icu.type, i18nIcuCases, icu.sourceSpan); 42876 icu.cases.forEach(caze => { 42877 i18nIcuCases[caze.value] = new Container(caze.expression.map(node => node.visit(this, context)), caze.expSourceSpan); 42878 }); 42879 context.icuDepth--; 42880 42881 if (context.isIcu || context.icuDepth > 0) { 42882 // Returns an ICU node when: 42883 // - the message (vs a part of the message) is an ICU message, or 42884 // - the ICU message is nested. 42885 const expPh = context.placeholderRegistry.getUniquePlaceholder(`VAR_${icu.type}`); 42886 i18nIcu.expressionPlaceholder = expPh; 42887 context.placeholderToContent[expPh] = { 42888 text: icu.switchValue, 42889 sourceSpan: icu.switchValueSourceSpan 42890 }; 42891 return context.visitNodeFn(icu, i18nIcu); 42892 } // Else returns a placeholder 42893 // ICU placeholders should not be replaced with their original content but with the their 42894 // translations. 42895 // TODO(vicb): add a html.Node -> i18n.Message cache to avoid having to re-create the msg 42896 42897 42898 const phName = context.placeholderRegistry.getPlaceholderName('ICU', icu.sourceSpan.toString()); 42899 context.placeholderToMessage[phName] = this.toI18nMessage([icu], '', '', '', undefined); 42900 const node = new IcuPlaceholder(i18nIcu, phName, icu.sourceSpan); 42901 return context.visitNodeFn(icu, node); 42902 } 42903 42904 visitExpansionCase(_icuCase, _context) { 42905 throw new Error('Unreachable code'); 42906 } 42907 /** 42908 * Convert, text and interpolated tokens up into text and placeholder pieces. 42909 * 42910 * @param tokens The text and interpolated tokens. 42911 * @param sourceSpan The span of the whole of the `text` string. 42912 * @param context The current context of the visitor, used to compute and store placeholders. 42913 * @param previousI18n Any i18n metadata associated with this `text` from a previous pass. 42914 */ 42915 42916 42917 _visitTextWithInterpolation(tokens, sourceSpan, context, previousI18n) { 42918 // Return a sequence of `Text` and `Placeholder` nodes grouped in a `Container`. 42919 const nodes = []; // We will only create a container if there are actually interpolations, 42920 // so this flag tracks that. 42921 42922 let hasInterpolation = false; 42923 42924 for (const token of tokens) { 42925 switch (token.type) { 42926 case 8 42927 /* TokenType.INTERPOLATION */ 42928 : 42929 case 17 42930 /* TokenType.ATTR_VALUE_INTERPOLATION */ 42931 : 42932 hasInterpolation = true; 42933 const expression = token.parts[1]; 42934 const baseName = extractPlaceholderName(expression) || 'INTERPOLATION'; 42935 const phName = context.placeholderRegistry.getPlaceholderName(baseName, expression); 42936 context.placeholderToContent[phName] = { 42937 text: token.parts.join(''), 42938 sourceSpan: token.sourceSpan 42939 }; 42940 nodes.push(new Placeholder(expression, phName, token.sourceSpan)); 42941 break; 42942 42943 default: 42944 if (token.parts[0].length > 0) { 42945 // This token is text or an encoded entity. 42946 // If it is following on from a previous text node then merge it into that node 42947 // Otherwise, if it is following an interpolation, then add a new node. 42948 const previous = nodes[nodes.length - 1]; 42949 42950 if (previous instanceof Text$2) { 42951 previous.value += token.parts[0]; 42952 previous.sourceSpan = new ParseSourceSpan(previous.sourceSpan.start, token.sourceSpan.end, previous.sourceSpan.fullStart, previous.sourceSpan.details); 42953 } else { 42954 nodes.push(new Text$2(token.parts[0], token.sourceSpan)); 42955 } 42956 } 42957 42958 break; 42959 } 42960 } 42961 42962 if (hasInterpolation) { 42963 // Whitespace removal may have invalidated the interpolation source-spans. 42964 reusePreviousSourceSpans(nodes, previousI18n); 42965 return new Container(nodes, sourceSpan); 42966 } else { 42967 return nodes[0]; 42968 } 42969 } 42970 42971} 42972/** 42973 * Re-use the source-spans from `previousI18n` metadata for the `nodes`. 42974 *
42975 * Whitespace removal can invalidate the source-spans of interpolation nodes, so we 42976 * reuse the source-span stored from a previous pass before the whitespace was removed. 42977 * 42978 * @param nodes The `Text` and `Placeholder` nodes to be processed. 42979 * @param previousI18n Any i18n metadata for these `nodes` stored from a previous pass. 42980 */ 42981 42982 42983function reusePreviousSourceSpans(nodes, previousI18n) { 42984 if (previousI18n instanceof Message) { 42985 // The `previousI18n` is an i18n `Message`, so we are processing an `Attribute` with i18n 42986 // metadata. The `Message` should consist only of a single `Container` that contains the 42987 // parts (`Text` and `Placeholder`) to process. 42988 assertSingleContainerMessage(previousI18n); 42989 previousI18n = previousI18n.nodes[0]; 42990 } 42991 42992 if (previousI18n instanceof Container) { 42993 // The `previousI18n` is a `Container`, which means that this is a second i18n extraction pass 42994 // after whitespace has been removed from the AST nodes. 42995 assertEquivalentNodes(previousI18n.children, nodes); // Reuse the source-spans from the first pass. 42996 42997 for (let i = 0; i < nodes.length; i++) { 42998 nodes[i].sourceSpan = previousI18n.children[i].sourceSpan; 42999 } 43000 } 43001} 43002/** 43003 * Asserts that the `message` contains exactly one `Container` node. 43004 */ 43005 43006 43007function assertSingleContainerMessage(message) { 43008 const nodes = message.nodes; 43009 43010 if (nodes.length !== 1 || !(nodes[0] instanceof Container)) { 43011 throw new Error('Unexpected previous i18n message - expected it to consist of only a single `Container` node.'); 43012 } 43013} 43014/** 43015 * Asserts that the `previousNodes` and `node` collections have the same number of elements and 43016 * corresponding elements have the same node type. 43017 */ 43018 43019 43020function assertEquivalentNodes(previousNodes, nodes) { 43021 if (previousNodes.length !== nodes.length) { 43022 throw new Error('The number of i18n message children changed between first and second pass.'); 43023 } 43024 43025 if (previousNodes.some((node, i) => nodes[i].constructor !== node.constructor)) { 43026 throw new Error('The types of the i18n message children changed between first and second pass.'); 43027 } 43028} 43029 43030const _CUSTOM_PH_EXP = /\/\/[\s\S]*i18n[\s\S]*\([\s\S]*ph[\s\S]*=[\s\S]*("|')([\s\S]*?)\1[\s\S]*\)/g; 43031 43032function extractPlaceholderName(input) { 43033 return input.split(_CUSTOM_PH_EXP)[2]; 43034} 43035/** 43036 * @license 43037 * Copyright Google LLC All Rights Reserved. 43038 * 43039 * Use of this source code is governed by an MIT-style license that can be 43040 * found in the LICENSE file at https://angular.io/license 43041 */ 43042 43043/** 43044 * An i18n error. 43045 */ 43046 43047 43048class I18nError extends ParseError { 43049 constructor(span, msg) { 43050 super(span, msg); 43051 } 43052 43053} 43054/** 43055 * @license 43056 * Copyright Google LLC All Rights Reserved. 43057 * 43058 * Use of this source code is governed by an MIT-style license that can be 43059 * found in the LICENSE file at https://angular.io/license 43060 */ 43061 43062 43063const setI18nRefs = (htmlNode, i18nNode) => { 43064 if (htmlNode instanceof NodeWithI18n) { 43065 if (i18nNode instanceof IcuPlaceholder && htmlNode.i18n instanceof Message) { 43066 // This html node represents an ICU but this is a second processing pass, and the legacy id 43067 // was computed in the previous pass and stored in the `i18n` property as a message. 43068 // We are about to wipe out that property so capture the previous message to be reused when 43069 // generating the message for this ICU later. See `_generateI18nMessage()`. 43070 i18nNode.previousMessage = htmlNode.i18n; 43071 } 43072 43073 htmlNode.i18n = i18nNode; 43074 } 43075 43076 return i18nNode; 43077}; 43078/** 43079 * This visitor walks over HTML parse tree and converts information stored in 43080 * i18n-related attributes ("i18n" and "i18n-*") into i18n meta object that is 43081 * stored with other element's and attribute's information. 43082 */ 43083 43084 43085class I18nMetaVisitor { 43086 constructor(interpolationConfig = DEFAULT_INTERPOLATION_CONFIG, keepI18nAttrs = false, enableI18nLegacyMessageIdFormat = false) { 43087 this.interpolationConfig = interpolationConfig; 43088 this.keepI18nAttrs = keepI18nAttrs; 43089 this.enableI18nLegacyMessageIdFormat = enableI18nLegacyMessageIdFormat; // whether visited nodes contain i18n information 43090 43091 this.hasI18nMeta = false;
43092 this._errors = []; // i18n message generation factory 43093 43094 this._createI18nMessage = createI18nMessageFactory(this.interpolationConfig); 43095 } 43096 43097 _generateI18nMessage(nodes, meta = '', visitNodeFn) { 43098 const { 43099 meaning, 43100 description, 43101 customId 43102 } = this._parseMetadata(meta); 43103 43104 const message = this._createI18nMessage(nodes, meaning, description, customId, visitNodeFn); 43105 43106 this._setMessageId(message, meta); 43107 43108 this._setLegacyIds(message, meta); 43109 43110 return message; 43111 } 43112 43113 visitAllWithErrors(nodes) { 43114 const result = nodes.map(node => node.visit(this, null)); 43115 return new ParseTreeResult(result, this._errors); 43116 } 43117 43118 visitElement(element) { 43119 let message = undefined; 43120 43121 if (hasI18nAttrs(element)) { 43122 this.hasI18nMeta = true; 43123 const attrs = []; 43124 const attrsMeta = {}; 43125 43126 for (const attr of element.attrs) { 43127 if (attr.name === I18N_ATTR) { 43128 // root 'i18n' node attribute 43129 const i18n = element.i18n || attr.value; 43130 message = this._generateI18nMessage(element.children, i18n, setI18nRefs); 43131 43132 if (message.nodes.length === 0) { 43133 // Ignore the message if it is empty. 43134 message = undefined; 43135 } // Store the message on the element 43136 43137 43138 element.i18n = message; 43139 } else if (attr.name.startsWith(I18N_ATTR_PREFIX)) { 43140 // 'i18n-*' attributes 43141 const name = attr.name.slice(I18N_ATTR_PREFIX.length); 43142 43143 if (isTrustedTypesSink(element.name, name)) { 43144 this._reportError(attr, `Translating attribute '${name}' is disallowed for security reasons.`); 43145 } else { 43146 attrsMeta[name] = attr.value; 43147 } 43148 } else { 43149 // non-i18n attributes 43150 attrs.push(attr); 43151 } 43152 } // set i18n meta for attributes 43153 43154 43155 if (Object.keys(attrsMeta).length) { 43156 for (const attr of attrs) { 43157 const meta = attrsMeta[attr.name]; // do not create translation for empty attributes 43158 43159 if (meta !== undefined && attr.value) { 43160 attr.i18n = this._generateI18nMessage([attr], attr.i18n || meta); 43161 } 43162 } 43163 } 43164 43165 if (!this.keepI18nAttrs) { 43166 // update element's attributes, 43167 // keeping only non-i18n related ones 43168 element.attrs = attrs; 43169 } 43170 } 43171 43172 visitAll(this, element.children, message); 43173 return element; 43174 } 43175 43176 visitExpansion(expansion, currentMessage) { 43177 let message; 43178 const meta = expansion.i18n; 43179 this.hasI18nMeta = true; 43180 43181 if (meta instanceof IcuPlaceholder) { 43182 // set ICU placeholder name (e.g. "ICU_1"), 43183 // generated while processing root element contents, 43184 // so we can reference it when we output translation 43185 const name = meta.name; 43186 message = this._generateI18nMessage([expansion], meta); 43187 const icu = icuFromI18nMessage(message); 43188 icu.name = name; 43189 43190 if (currentMessage !== null) { 43191 // Also update the placeholderToMessage map with this new message 43192 currentMessage.placeholderToMessage[name] = message; 43193 } 43194 } else { 43195 // ICU is a top level message, try to use metadata from container element if provided via 43196 // `context` argument. Note: context may not be available for standalone ICUs (without 43197 // wrapping element), so fallback to ICU metadata in this case. 43198 message = this._generateI18nMessage([expansion], currentMessage || meta); 43199 } 43200 43201 expansion.i18n = message; 43202 return expansion; 43203 } 43204 43205 visitText(text) { 43206 return text; 43207 } 43208 43209 visitAttribute(attribute) { 43210 return attribute; 43211 } 43212 43213 visitComment(comment) { 43214 return comment; 43215 } 43216 43217 visitExpansionCase(expansionCase) { 43218 return expansionCase; 43219 } 43220 /** 43221 * Parse the general form `meta` passed into extract the explicit metadata needed to create a 43222 * `Message`. 43223 * 43224 * There are three possibilities for the `meta` variable 43225 * 1) a string from an `i18n` template attribute: parse it to extract the metadata values. 43226 * 2) a `Message` from a previous processing pass: reuse the metadata values in the message. 43227 * 4) other: ignore this and just process the message metadata as normal 43228 * 43229 * @param meta the bucket that holds information about the message 43230 * @returns the parsed metadata. 43231 */ 43232 43233 43234 _parseMetadata(meta) { 43235 return typeof meta === 'string' ? parseI18nMeta(meta) : meta instanceof Message ? meta : {}; 43236 } 43237 /** 43238 * Generate (or restore) message id if not specified already. 43239 */ 43240 43241 43242 _setMessageId(message, meta) { 43243 if (!message.id) { 43244 message.id = meta instanceof Message && meta.id || decimalDigest(message); 43245 } 43246 } 43247 /** 43248 * Update the `message` with a `legacyId` if necessary. 43249 * 43250 * @param message the message whose legacy id should be set 43251 * @param meta information about the message being processed 43252 */ 43253 43254 43255 _setLegacyIds(message, meta) { 43256 if (this.enableI18nLegacyMessageIdFormat) { 43257 message.legacyIds = [computeDigest(message), computeDecimalDigest(message)]; 43258 } else if (typeof meta !== 'string') { 43259 // This occurs if we are doing the 2nd pass after whitespace removal (see `parseTemplate()` in 43260 // `packages/compiler/src/render3/view/template.ts`). 43261 // In that case we want to reuse the legacy message generated in the 1st pass (see 43262 // `setI18nRefs()`). 43263 const previousMessage = meta instanceof Message ? meta : meta instanceof IcuPlaceholder ? meta.previousMessage : undefined; 43264 message.legacyIds = previousMessage ? previousMessage.legacyIds : []; 43265 } 43266 } 43267 43268 _reportError(node, msg) { 43269 this._errors.push(new I18nError(node.sourceSpan, msg)); 43270 } 43271 43272} 43273/** I18n separators for metadata **/ 43274 43275 43276const I18N_MEANING_SEPARATOR = '|'; 43277const I18N_ID_SEPARATOR = '@@'; 43278/** 43279 * Parses i18n metas like:
43280 * - "@@id", 43281 * - "description[@@id]", 43282 * - "meaning|description[@@id]" 43283 * and returns an object with parsed output. 43284 * 43285 * @param meta String that represents i18n meta 43286 * @returns Object with id, meaning and description fields 43287 */ 43288 43289function parseI18nMeta(meta = '') { 43290 let customId; 43291 let meaning; 43292 let description; 43293 meta = meta.trim(); 43294 43295 if (meta) { 43296 const idIndex = meta.indexOf(I18N_ID_SEPARATOR); 43297 const descIndex = meta.indexOf(I18N_MEANING_SEPARATOR); 43298 let meaningAndDesc; 43299 [meaningAndDesc, customId] = idIndex > -1 ? [meta.slice(0, idIndex), meta.slice(idIndex + 2)] : [meta, '']; 43300 [meaning, description] = descIndex > -1 ? [meaningAndDesc.slice(0, descIndex), meaningAndDesc.slice(descIndex + 1)] : ['', meaningAndDesc]; 43301 } 43302 43303 return { 43304 customId, 43305 meaning, 43306 description 43307 }; 43308} // Converts i18n meta information for a message (id, description, meaning) 43309// to a JsDoc statement formatted as expected by the Closure compiler. 43310 43311 43312function i18nMetaToJSDoc(meta) { 43313 const tags = []; 43314 43315 if (meta.description) { 43316 tags.push({ 43317 tagName: "desc" 43318 /* o.JSDocTagName.Desc */ 43319 , 43320 text: meta.description 43321 }); 43322 } else { 43323 // Suppress the JSCompiler warning that a `@desc` was not given for this message. 43324 tags.push({ 43325 tagName: "suppress" 43326 /* o.JSDocTagName.Suppress */ 43327 , 43328 text: '{msgDescriptions}' 43329 }); 43330 } 43331 43332 if (meta.meaning) { 43333 tags.push({ 43334 tagName: "meaning" 43335 /* o.JSDocTagName.Meaning */ 43336 , 43337 text: meta.meaning 43338 }); 43339 } 43340 43341 return jsDocComment(tags); 43342} 43343/** Closure uses `goog.getMsg(message)` to lookup translations */ 43344 43345 43346const GOOG_GET_MSG = 'goog.getMsg'; 43347/** 43348 * Generates a `goog.getMsg()` statement and reassignment. The template: 43349 * 43350 * ```html 43351 * <div i18n>Sent from {{ sender }} to <span class="receiver">{{ receiver }}</span></div> 43352 * ``` 43353 * 43354 * Generates: 43355 * 43356 * ```typescript 43357 * const MSG_FOO = goog.getMsg( 43358 * // Message template. 43359 * 'Sent from {$interpolation} to {$startTagSpan}{$interpolation_1}{$closeTagSpan}.', 43360 * // Placeholder values, set to magic strings which get replaced by the Angular runtime. 43361 * { 43362 * 'interpolation': '\uFFFD0\uFFFD', 43363 * 'startTagSpan': '\uFFFD1\uFFFD', 43364 * 'interpolation_1': '\uFFFD2\uFFFD', 43365 * 'closeTagSpan': '\uFFFD3\uFFFD', 43366 * }, 43367 * // Options bag. 43368 * { 43369 * // Maps each placeholder to the original Angular source code which generates it's value. 43370 * original_code: { 43371 * 'interpolation': '{{ sender }}', 43372 * 'startTagSpan': '<span class="receiver">', 43373 * 'interpolation_1': '{{ receiver }}', 43374 * 'closeTagSpan': '</span>', 43375 * }, 43376 * }, 43377 * ); 43378 * const I18N_0 = MSG_FOO; 43379 * ``` 43380 */ 43381 43382function createGoogleGetMsgStatements(variable$1, message, closureVar, placeholderValues) { 43383 const messageString = serializeI18nMessageForGetMsg(message); 43384 const args = [literal(messageString)]; 43385 43386 if (Object.keys(placeholderValues).length) { 43387 // Message template parameters containing the magic strings replaced by the Angular runtime with 43388 // real data, e.g. `{'interpolation': '\uFFFD0\uFFFD'}`. 43389 args.push(mapLiteral(formatI18nPlaceholderNamesInMap(placeholderValues, true 43390 /* useCamelCase */ 43391 ), true 43392 /* quoted */ 43393 )); // Message options object, which contains original source code for placeholders (as they are 43394 // present in a template, e.g. 43395 // `{original_code: {'interpolation': '{{ name }}', 'startTagSpan': '<span>'}}`. 43396 43397 args.push(mapLiteral({ 43398 original_code: literalMap(Object.keys(placeholderValues).map(param => ({ 43399 key: formatI18nPlaceholderName(param), 43400 quoted: true, 43401 value: message.placeholders[param] ? // Get source span for typical placeholder if it exists. 43402 literal(message.placeholders[param].sourceSpan.toString()) : // Otherwise must be an ICU expression, get it's source span. 43403 literal(message.placeholderToMessage[param].nodes.map(node => node.sourceSpan.toString()).join('')) 43404 }))) 43405 })); 43406 } // /** 43407 // * @desc description of message 43408 // * @meaning meaning of message 43409 // */ 43410 // const MSG_... = goog.getMsg(..); 43411 // I18N_X = MSG_...; 43412 43413 43414 const googGetMsgStmt = closureVar.set(variable(GOOG_GET_MSG).callFn(args)).toConstDecl(); 43415 googGetMsgStmt.addLeadingComment(i18nMetaToJSDoc(message));
43416 const i18nAssignmentStmt = new ExpressionStatement(variable$1.set(closureVar)); 43417 return [googGetMsgStmt, i18nAssignmentStmt]; 43418} 43419/** 43420 * This visitor walks over i18n tree and generates its string representation, including ICUs and 43421 * placeholders in `{$placeholder}` (for plain messages) or `{PLACEHOLDER}` (inside ICUs) format. 43422 */ 43423 43424 43425class GetMsgSerializerVisitor { 43426 formatPh(value) { 43427 return `{$${formatI18nPlaceholderName(value)}}`; 43428 } 43429 43430 visitText(text) { 43431 return text.value; 43432 } 43433 43434 visitContainer(container) { 43435 return container.children.map(child => child.visit(this)).join(''); 43436 } 43437 43438 visitIcu(icu) { 43439 return serializeIcuNode(icu); 43440 } 43441 43442 visitTagPlaceholder(ph) { 43443 return ph.isVoid ? this.formatPh(ph.startName) : `${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${this.formatPh(ph.closeName)}`; 43444 } 43445 43446 visitPlaceholder(ph) { 43447 return this.formatPh(ph.name); 43448 } 43449 43450 visitIcuPlaceholder(ph, context) { 43451 return this.formatPh(ph.name); 43452 } 43453 43454} 43455 43456const serializerVisitor = new GetMsgSerializerVisitor(); 43457 43458function serializeI18nMessageForGetMsg(message) { 43459 return message.nodes.map(node => node.visit(serializerVisitor, null)).join(''); 43460} 43461 43462function createLocalizeStatements(variable, message, params) { 43463 const { 43464 messageParts, 43465 placeHolders 43466 } = serializeI18nMessageForLocalize(message); 43467 const sourceSpan = getSourceSpan(message); 43468 const expressions = placeHolders.map(ph => params[ph.text]); 43469 const localizedString$1 = localizedString(message, messageParts, placeHolders, expressions, sourceSpan); 43470 const variableInitialization = variable.set(localizedString$1); 43471 return [new ExpressionStatement(variableInitialization)]; 43472} 43473/** 43474 * This visitor walks over an i18n tree, capturing literal strings and placeholders. 43475 * 43476 * The result can be used for generating the `$localize` tagged template literals. 43477 */ 43478 43479 43480class LocalizeSerializerVisitor { 43481 constructor(placeholderToMessage, pieces) { 43482 this.placeholderToMessage = placeholderToMessage; 43483 this.pieces = pieces; 43484 } 43485 43486 visitText(text) { 43487 if (this.pieces[this.pieces.length - 1] instanceof LiteralPiece) { 43488 // Two literal pieces in a row means that there was some comment node in-between. 43489 this.pieces[this.pieces.length - 1].text += text.value; 43490 } else { 43491 const sourceSpan = new ParseSourceSpan(text.sourceSpan.fullStart, text.sourceSpan.end, text.sourceSpan.fullStart, text.sourceSpan.details); 43492 this.pieces.push(new LiteralPiece(text.value, sourceSpan)); 43493 } 43494 } 43495 43496 visitContainer(container) { 43497 container.children.forEach(child => child.visit(this)); 43498 } 43499 43500 visitIcu(icu) { 43501 this.pieces.push(new LiteralPiece(serializeIcuNode(icu), icu.sourceSpan)); 43502 } 43503 43504 visitTagPlaceholder(ph) { 43505 this.pieces.push(this.createPlaceholderPiece(ph.startName, ph.startSourceSpan ?? ph.sourceSpan)); 43506 43507 if (!ph.isVoid) { 43508 ph.children.forEach(child => child.visit(this)); 43509 this.pieces.push(this.createPlaceholderPiece(ph.closeName, ph.endSourceSpan ?? ph.sourceSpan)); 43510 } 43511 } 43512 43513 visitPlaceholder(ph) { 43514 this.pieces.push(this.createPlaceholderPiece(ph.name, ph.sourceSpan)); 43515 } 43516 43517 visitIcuPlaceholder(ph) { 43518 this.pieces.push(this.createPlaceholderPiece(ph.name, ph.sourceSpan, this.placeholderToMessage[ph.name])); 43519 } 43520 43521 createPlaceholderPiece(name, sourceSpan, associatedMessage) { 43522 return new PlaceholderPiece(formatI18nPlaceholderName(name, 43523 /* useCamelCase */ 43524 false), sourceSpan, associatedMessage); 43525 } 43526 43527} 43528/** 43529 * Serialize an i18n message into two arrays: messageParts and placeholders. 43530 * 43531 * These arrays will be used to generate `$localize` tagged template literals. 43532 * 43533 * @param message The message to be serialized.
43534 * @returns an object containing the messageParts and placeholders. 43535 */ 43536 43537 43538function serializeI18nMessageForLocalize(message) { 43539 const pieces = []; 43540 const serializerVisitor = new LocalizeSerializerVisitor(message.placeholderToMessage, pieces); 43541 message.nodes.forEach(node => node.visit(serializerVisitor)); 43542 return processMessagePieces(pieces); 43543} 43544 43545function getSourceSpan(message) { 43546 const startNode = message.nodes[0]; 43547 const endNode = message.nodes[message.nodes.length - 1]; 43548 return new ParseSourceSpan(startNode.sourceSpan.fullStart, endNode.sourceSpan.end, startNode.sourceSpan.fullStart, startNode.sourceSpan.details); 43549} 43550/** 43551 * Convert the list of serialized MessagePieces into two arrays. 43552 * 43553 * One contains the literal string pieces and the other the placeholders that will be replaced by 43554 * expressions when rendering `$localize` tagged template literals. 43555 * 43556 * @param pieces The pieces to process. 43557 * @returns an object containing the messageParts and placeholders. 43558 */ 43559 43560 43561function processMessagePieces(pieces) { 43562 const messageParts = []; 43563 const placeHolders = []; 43564 43565 if (pieces[0] instanceof PlaceholderPiece) { 43566 // The first piece was a placeholder so we need to add an initial empty message part. 43567 messageParts.push(createEmptyMessagePart(pieces[0].sourceSpan.start)); 43568 } 43569 43570 for (let i = 0; i < pieces.length; i++) { 43571 const part = pieces[i]; 43572 43573 if (part instanceof LiteralPiece) { 43574 messageParts.push(part); 43575 } else { 43576 placeHolders.push(part); 43577 43578 if (pieces[i - 1] instanceof PlaceholderPiece) { 43579 // There were two placeholders in a row, so we need to add an empty message part. 43580 messageParts.push(createEmptyMessagePart(pieces[i - 1].sourceSpan.end)); 43581 } 43582 } 43583 } 43584 43585 if (pieces[pieces.length - 1] instanceof PlaceholderPiece) { 43586 // The last piece was a placeholder so we need to add a final empty message part. 43587 messageParts.push(createEmptyMessagePart(pieces[pieces.length - 1].sourceSpan.end)); 43588 } 43589 43590 return { 43591 messageParts, 43592 placeHolders 43593 }; 43594} 43595 43596function createEmptyMessagePart(location) { 43597 return new LiteralPiece('', new ParseSourceSpan(location, location)); 43598} 43599/** 43600 * @license 43601 * Copyright Google LLC All Rights Reserved. 43602 * 43603 * Use of this source code is governed by an MIT-style license that can be 43604 * found in the LICENSE file at https://angular.io/license 43605 */ 43606// Selector attribute name of `<ng-content>` 43607 43608 43609const NG_CONTENT_SELECT_ATTR = 'select'; // Attribute name of `ngProjectAs`. 43610 43611const NG_PROJECT_AS_ATTR_NAME = 'ngProjectAs'; // Global symbols available only inside event bindings. 43612 43613const EVENT_BINDING_SCOPE_GLOBALS = new Set(['$event']); // List of supported global targets for event listeners 43614 43615const GLOBAL_TARGET_RESOLVERS = new Map([['window', Identifiers.resolveWindow], ['document', Identifiers.resolveDocument], ['body', Identifiers.resolveBody]]); 43616const LEADING_TRIVIA_CHARS = [' ', '\n', '\r', '\t']; // if (rf & flags) { .. } 43617 43618function renderFlagCheckIfStmt(flags, statements) { 43619 return ifStmt(variable(RENDER_FLAGS).bitwiseAnd(literal(flags), null, false), statements); 43620} 43621 43622function prepareEventListenerParameters(eventAst, handlerName = null, scope = null) { 43623 const { 43624 type, 43625 name, 43626 target, 43627 phase, 43628 handler 43629 } = eventAst; 43630 43631 if (target && !GLOBAL_TARGET_RESOLVERS.has(target)) { 43632 throw new Error(`Unexpected global target '${target}' defined for '${name}' event. 43633 Supported list of global targets: ${Array.from(GLOBAL_TARGET_RESOLVERS.keys())}.`); 43634 } 43635 43636 const eventArgumentName = '$event'; 43637 const implicitReceiverAccesses = new Set(); 43638 const implicitReceiverExpr = scope === null || scope.bindingLevel === 0 ? variable(CONTEXT_NAME) : scope.getOrCreateSharedContextVar(0); 43639 const bindingStatements = convertActionBinding(scope, implicitReceiverExpr, handler, 'b', eventAst.handlerSpan, implicitReceiverAccesses, EVENT_BINDING_SCOPE_GLOBALS); 43640 const statements = []; 43641 const variableDeclarations = scope?.variableDeclarations();
43642 const restoreViewStatement = scope?.restoreViewStatement(); 43643 43644 if (variableDeclarations) { 43645 // `variableDeclarations` needs to run first, because 43646 // `restoreViewStatement` depends on the result. 43647 statements.push(...variableDeclarations); 43648 } 43649 43650 statements.push(...bindingStatements); 43651 43652 if (restoreViewStatement) { 43653 statements.unshift(restoreViewStatement); // If there's a `restoreView` call, we need to reset the view at the end of the listener 43654 // in order to avoid a leak. If there's a `return` statement already, we wrap it in the 43655 // call, e.g. `return resetView(ctx.foo())`. Otherwise we add the call as the last statement. 43656 43657 const lastStatement = statements[statements.length - 1]; 43658 43659 if (lastStatement instanceof ReturnStatement) { 43660 statements[statements.length - 1] = new ReturnStatement(invokeInstruction(lastStatement.value.sourceSpan, Identifiers.resetView, [lastStatement.value])); 43661 } else { 43662 statements.push(new ExpressionStatement(invokeInstruction(null, Identifiers.resetView, []))); 43663 } 43664 } 43665 43666 const eventName = type === 1 43667 /* ParsedEventType.Animation */ 43668 ? prepareSyntheticListenerName(name, phase) : name; 43669 const fnName = handlerName && sanitizeIdentifier(handlerName); 43670 const fnArgs = []; 43671 43672 if (implicitReceiverAccesses.has(eventArgumentName)) { 43673 fnArgs.push(new FnParam(eventArgumentName, DYNAMIC_TYPE)); 43674 } 43675 43676 const handlerFn = fn(fnArgs, statements, INFERRED_TYPE, null, fnName); 43677 const params = [literal(eventName), handlerFn]; 43678 43679 if (target) { 43680 params.push(literal(false), // `useCapture` flag, defaults to `false` 43681 importExpr(GLOBAL_TARGET_RESOLVERS.get(target))); 43682 } 43683 43684 return params; 43685} 43686 43687function createComponentDefConsts() { 43688 return { 43689 prepareStatements: [], 43690 constExpressions: [], 43691 i18nVarRefsCache: new Map() 43692 }; 43693} 43694 43695class TemplateDefinitionBuilder { 43696 constructor(constantPool, parentBindingScope, level = 0, contextName, i18nContext, templateIndex, templateName, _namespace, relativeContextFilePath, i18nUseExternalIds, _constants = createComponentDefConsts()) { 43697 this.constantPool = constantPool; 43698 this.level = level; 43699 this.contextName = contextName; 43700 this.i18nContext = i18nContext; 43701 this.templateIndex = templateIndex; 43702 this.templateName = templateName; 43703 this._namespace = _namespace; 43704 this.i18nUseExternalIds = i18nUseExternalIds; 43705 this._constants = _constants; 43706 this._dataIndex = 0; 43707 this._bindingContext = 0; 43708 this._prefixCode = []; 43709 /** 43710 * List of callbacks to generate creation mode instructions. We store them here as we process 43711 * the template so bindings in listeners are resolved only once all nodes have been visited. 43712 * This ensures all local refs and context variables are available for matching. 43713 */ 43714 43715 this._creationCodeFns = []; 43716 /** 43717 * List of callbacks to generate update mode instructions. We store them here as we process 43718 * the template so bindings are resolved only once all nodes have been visited. This ensures 43719 * all local refs and context variables are available for matching. 43720 */ 43721 43722 this._updateCodeFns = []; 43723 /** Index of the currently-selected node. */ 43724 43725 this._currentIndex = 0; 43726 /** Temporary variable declarations generated from visiting pipes, literals, etc. */ 43727 43728 this._tempVariables = []; 43729 /** 43730 * List of callbacks to build nested templates. Nested templates must not be visited until 43731 * after the parent template has finished visiting all of its nodes. This ensures that all 43732 * local ref bindings in nested templates are able to find local ref values if the refs 43733 * are defined after the template declaration. 43734 */ 43735 43736 this._nestedTemplateFns = []; // i18n context local to this template 43737 43738 this.i18n = null; // Number of slots to reserve for pureFunctions 43739 43740 this._pureFunctionSlots = 0; // Number of binding slots 43741 43742 this._bindingSlots = 0; // Projection slots found in the template. Projection slots can distribute projected 43743 // nodes based on a selector, or can just use the wildcard selector to match 43744 // all nodes which aren't matching any selector. 43745 43746 this._ngContentReservedSlots = []; // Number of non-default selectors found in all parent templates of this template. We need to 43747 // track it to properly adjust projection slot index in the `projection` instruction. 43748 43749 this._ngContentSelectorsOffset = 0; // Expression that should be used as implicit receiver when convert
43749ing template 43750 // expressions to output AST. 43751 43752 this._implicitReceiverExpr = null; // These should be handled in the template or element directly. 43753 43754 this.visitReference = invalid; 43755 this.visitVariable = invalid; 43756 this.visitTextAttribute = invalid; 43757 this.visitBoundAttribute = invalid; 43758 this.visitBoundEvent = invalid; 43759 this._bindingScope = parentBindingScope.nestedScope(level); // Turn the relative context file path into an identifier by replacing non-alphanumeric 43760 // characters with underscores. 43761 43762 this.fileBasedI18nSuffix = relativeContextFilePath.replace(/[^A-Za-z0-9]/g, '_') + '_'; 43763 this._valueConverter = new ValueConverter(constantPool, () => this.allocateDataSlot(), numSlots => this.allocatePureFunctionSlots(numSlots), (name, localName, slot, value) => { 43764 this._bindingScope.set(this.level, localName, value); 43765 43766 this.creationInstruction(null, Identifiers.pipe, [literal(slot), literal(name)]); 43767 }); 43768 } 43769 43770 buildTemplateFunction(nodes, variables, ngContentSelectorsOffset = 0, i18n) { 43771 this._ngContentSelectorsOffset = ngContentSelectorsOffset; 43772 43773 if (this._namespace !== Identifiers.namespaceHTML) { 43774 this.creationInstruction(null, this._namespace); 43775 } // Create variable bindings 43776 43777
43778 variables.forEach(v => this.registerContextVariables(v)); // Initiate i18n context in case: 43779 // - this template has parent i18n context 43780 // - or the template has i18n meta associated with it, 43781 // but it's not initiated by the Element (e.g. <ng-template i18n>) 43782 43783 const initI18nContext = this.i18nContext || isI18nRootNode(i18n) && !isSingleI18nIcu(i18n) && !(isSingleElementTemplate(nodes) && nodes[0].i18n === i18n); 43784 const selfClosingI18nInstruction = hasTextChildrenOnly(nodes); 43785 43786 if (initI18nContext) { 43787 this.i18nStart(null, i18n, selfClosingI18nInstruction); 43788 } // This is the initial pass through the nodes of this template. In this pass, we 43789 // queue all creation mode and update mode instructions for generation in the second 43790 // pass. It's necessary to separate the passes to ensure local refs are defined before 43791 // resolving bindings. We also count bindings in this pass as we walk bound expressions. 43792 43793 43794 visitAll$1(this, nodes); // Add total binding count to pure function count so pure function instructions are 43795 // generated with the correct slot offset when update instructions are processed. 43796 43797 this._pureFunctionSlots += this._bindingSlots; // Pipes are walked in the first pass (to enqueue `pipe()` creation instructions and 43798 // `pipeBind` update instructions), so we have to update the slot offsets manually 43799 // to account for bindings. 43800 43801 this._valueConverter.updatePipeSlotOffsets(this._bindingSlots); // Nested templates must be processed before creation instructions so template() 43802 // instructions can be generated with the correct internal const count. 43803 43804 43805 this._nestedTemplateFns.forEach(buildTemplateFn => buildTemplateFn()); // Output the `projectionDef` instruction when some `<ng-content>` tags are present. 43806 // The `projectionDef` instruction is only emitted for the component template and 43807 // is skipped for nested templates (<ng-template> tags). 43808 43809 43810 if (this.level === 0 && this._ngContentReservedSlots.length) { 43811 const parameters = []; // By default the `projectionDef` instructions creates one slot for the wildcard 43812 // selector if no parameters are passed. Therefore we only want to allocate a new 43813 // array for the projection slots if the default projection slot is not sufficient. 43814 43815 if (this._ngContentReservedSlots.length > 1 || this._ngContentReservedSlots[0] !== '*') { 43816 const r3ReservedSlots = this._ngContentReservedSlots.map(s => s !== '*' ? parseSelectorToR3Selector(s) : s); 43817 43818 parameters.push(this.constantPool.getConstLiteral(asLiteral(r3ReservedSlots), true)); 43819 } // Since we accumulate ngContent selectors while processing template elements, 43820 // we *prepend* `projectionDef` to creation instructions block, to put it before 43821 // any `projection` instructions 43822 43823 43824 this.creationInstruction(null, Identifiers.projectionDef, parameters, 43825 /* prepend */ 43826 true); 43827 } 43828 43829 if (initI18nContext) { 43830 this.i18nEnd(null, selfClosingI18nInstruction); 43831 } // Generate all the creation mode instructions (e.g. resolve bindings in listeners) 43832 43833 43834 const creationStatements = getInstructionStatements(this._creationCodeFns); // Generate all the update mode instructions (e.g. resolve property or text bindings) 43835 43836 const updateStatements = getInstructionStatements(this._updateCodeFns); // Variable declaration must occur after binding resolution so we can generate context 43837 // instructions that build on each other. 43838 // e.g. const b = nextContext().$implicit(); const b = nextContext(); 43839 43840 const creationVariables = this._bindingScope.viewSnapshotStatements(); 43841 43842 const updateVariables = this._bindingScope.variableDeclarations().concat(this._tempVariables); 43843 43844 const creationBlock = creationStatements.length > 0 ? [renderFlagCheckIfStmt(1 43845 /* core.RenderFlags.Create */ 43846 , creationVariables.concat(creationStatements))] : []; 43847 const updateBlock = updateStatements.length > 0 ? [renderFlagCheckIfStmt(2 43848 /* core.RenderFlags.Update */ 43849 , updateVariables.concat(updateStatements))] : []; 43850 return fn( // i.e. (rf: RenderFlags, ctx: any) 43851 [new FnParam(RENDER_FLAGS, NUMBER_TYPE), new FnParam(CONTEXT_NAME, null)], [// Temporary variable declarations for query refresh (i.e. let _t: any;) 43852 ...this._prefixCode, // Creating mode (i.e. if (rf & RenderFlags.
43852Create) { ... }) 43853 ...creationBlock, // Binding and refresh mode (i.e. if (rf & RenderFlags.Update) {...}) 43854 ...updateBlock], INFERRED_TYPE, null, this.templateName); 43855 } // LocalResolver 43856 43857 43858 getLocal(name) { 43859 return this._bindingScope.get(name); 43860 } // LocalResolver 43861 43862 43863 notifyImplicitReceiverUse() { 43864 this._bindingScope.notifyImplicitReceiverUse(); 43865 } // LocalResolver 43866 43867 43868 maybeRestoreView() { 43869 this._bindingScope.maybeRestoreView(); 43870 } 43871 43872 i18nTranslate(message, params = {}, ref, transformFn) { 43873 const _ref = ref || this.i18nGenerateMainBlockVar(); // Closure Compiler requires const names to start with `MSG_` but disallows any other const to 43874 // start with `MSG_`. We define a variable starting with `MSG_` just for the `goog.getMsg` call 43875 43876 43877 const closureVar = this.i18nGenerateClosureVar(message.id); 43878 const statements = getTranslationDeclStmts(message, _ref, closureVar, params, transformFn); 43879 43880 this._constants.prepareStatements.push(...statements); 43881 43882 return _ref; 43883 } 43884 43885 registerContextVariables(variable$1) { 43886 const scopedName = this._bindingScope.freshReferenceName(); 43887 43888 const retrievalLevel = this.level; 43889 const lhs = variable(variable$1.name + scopedName); 43890 43891 this._bindingScope.set(retrievalLevel, variable$1.name, lhs, 1 43892 /* DeclarationPriority.CONTEXT */ 43893 , (scope, relativeLevel) => { 43894 let rhs; 43895 43896 if (scope.bindingLevel === retrievalLevel) { 43897 if (scope.isListenerScope() && scope.hasRestoreViewVariable()) { 43898 // e.g. restoredCtx. 43899 // We have to get the context from a view reference, if one is available, because 43900 // the context that was passed in during creation may not be correct anymore. 43901 // For more information see: https://github.com/angular/angular/pull/40360. 43902 rhs = variable(RESTORED_VIEW_CONTEXT_NAME); 43903 scope.notifyRestoredViewContextUse(); 43904 } else { 43905 // e.g. ctx 43906 rhs = variable(CONTEXT_NAME); 43907 } 43908 } else { 43909 const sharedCtxVar = scope.getSharedContextName(retrievalLevel); // e.g. ctx_r0 OR x(2); 43910 43911 rhs = sharedCtxVar ? sharedCtxVar : generateNextContextExpr(relativeLevel); 43912 } // e.g. const $item$ = x(2).$implicit; 43913 43914 43915 return [lhs.set(rhs.prop(variable$1.value || IMPLICIT_REFERENCE)).toConstDecl()]; 43916 }); 43917 } 43918 43919 i18nAppendBindings(expressions) { 43920 if (expressions.length > 0) { 43921 expressions.forEach(expression => this.i18n.appendBinding(expression)); 43922 } 43923 } 43924 43925 i18nBindProps(props) { 43926 const bound = {}; 43927 Object.keys(props).forEach(key => { 43928 const prop = props[key]; 43929 43930 if (prop instanceof Text$3) { 43931 bound[key] = literal(prop.value); 43932 } else { 43933 const value = prop.value.visit(this._valueConverter); 43934 this.allocateBindingSlots(value); 43935 43936 if (value instanceof Interpolation) { 43937 const { 43938 strings, 43939 expressions 43940 } = value; 43941 const { 43942 id, 43943 bindings 43944 } = this.i18n; 43945 const label = assembleI18nBoundString(strings, bindings.size, id); 43946 this.i18nAppendBindings(expressions); 43947 bound[key] = literal(label); 43948 } 43949 } 43950 }); 43951 return bound; 43952 } // Generates top level vars for i18n blocks (i.e. `i18n_N`). 43953 43954 43955 i18nGenerateMainBlockVar() { 43956 return variable(this.constantPool.uniqueName(TRANSLATION_VAR_PREFIX)); 43957 } // Generates vars with Closure-specific names for i18n blocks (i.e. `MSG_XXX`). 43958 43959 43960 i18nGenerateClosureVar(messageId) { 43961 let name; 43962 const suffix = this.fileBasedI18nSuffix.toUpperCase(); 43963 43964 if (this.i18nUseExternalIds) { 43965 const prefix = getTranslationConstPrefix(`EXTERNAL_`); 43966 const uniqueSuffix = this.constantPool.uniqueName(suffix); 43967 name = `${prefix}${sanitizeIdentifier(messageId)}$$${uniqueSuffix}`; 43968 } else { 43969 const prefix = getTranslationConstPrefix(suffix); 43970 name = this.constantPool.uniqueName(prefix); 43971 } 43972 43973 return variable(name); 43974 } 43975 43976 i18nUpdateRef(context) { 43977 const { 43978 icus, 43979 meta, 43980 isRoot, 43981 isResolved, 43982 isEmitted 43983 } = context; 43984 43985 if (isRoot && isResolved && !isEmitted && !isSingleI18nIcu(meta)) {
43986 context.isEmitted = true; 43987 const placeholders = context.getSerializedPlaceholders(); 43988 let icuMapping = {}; 43989 let params = placeholders.size ? placeholdersToParams(placeholders) : {}; 43990 43991 if (icus.size) { 43992 icus.forEach((refs, key) => { 43993 if (refs.length === 1) { 43994 // if we have one ICU defined for a given 43995 // placeholder - just output its reference 43996 params[key] = refs[0]; 43997 } else { 43998 // ... otherwise we need to activate post-processing 43999 // to replace ICU placeholders with proper values 44000 const placeholder = wrapI18nPlaceholder(`${I18N_ICU_MAPPING_PREFIX}${key}`); 44001 params[key] = literal(placeholder); 44002 icuMapping[key] = literalArr(refs); 44003 } 44004 }); 44005 } // translation requires post processing in 2 cases: 44006 // - if we have placeholders with multiple values (ex. `START_DIV`: [�#1�, �#2�, ...]) 44007 // - if we have multiple ICUs that refer to the same placeholder name 44008 44009 44010 const needsPostprocessing = Array.from(placeholders.values()).some(value => value.length > 1) || Object.keys(icuMapping).length; 44011 let transformFn; 44012 44013 if (needsPostprocessing) { 44014 transformFn = raw => { 44015 const args = [raw]; 44016 44017 if (Object.keys(icuMapping).length) { 44018 args.push(mapLiteral(icuMapping, true)); 44019 } 44020 44021 return invokeInstruction(null, Identifiers.i18nPostprocess, args); 44022 }; 44023 } 44024 44025 this.i18nTranslate(meta, params, context.ref, transformFn); 44026 } 44027 } 44028 44029 i18nStart(span = null, meta, selfClosing) { 44030 const index = this.allocateDataSlot(); 44031 this.i18n = this.i18nContext ? this.i18nContext.forkChildContext(index, this.templateIndex, meta) : new I18nContext(index, this.i18nGenerateMainBlockVar(), 0, this.templateIndex, meta); // generate i18nStart instruction 44032 44033 const { 44034 id, 44035 ref 44036 } = this.i18n; 44037 const params = [literal(index), this.addToConsts(ref)]; 44038 44039 if (id > 0) { 44040 // do not push 3rd argument (sub-block id) 44041 // into i18nStart call for top level i18n context 44042 params.push(literal(id)); 44043 } 44044 44045 this.creationInstruction(span, selfClosing ? Identifiers.i18n : Identifiers.i18nStart, params); 44046 } 44047 44048 i18nEnd(span = null, selfClosing) { 44049 if (!this.i18n) { 44050 throw new Error('i18nEnd is executed with no i18n context present'); 44051 } 44052 44053 if (this.i18nContext) { 44054 this.i18nContext.reconcileChildContext(this.i18n); 44055 this.i18nUpdateRef(this.i18nContext); 44056 } else { 44057 this.i18nUpdateRef(this.i18n); 44058 } // setup accumulated bindings 44059 44060 44061 const { 44062 index, 44063 bindings 44064 } = this.i18n; 44065 44066 if (bindings.size) { 44067 for (const binding of bindings) { 44068 // for i18n block, advance to the most recent element index (by taking the current number of 44069 // elements and subtracting one) before invoking `i18nExp` instructions, to make sure the 44070 // necessary lifecycle hooks of components/directives are properly flushed. 44071 this.updateInstructionWithAdvance(this.getConstCount() - 1, span, Identifiers.i18nExp, () => this.convertPropertyBinding(binding)); 44072 } 44073 44074 this.updateInstruction(span, Identifiers.i18nApply, [literal(index)]); 44075 } 44076 44077 if (!selfClosing) { 44078 this.creationInstruction(span, Identifiers.i18nEnd); 44079 } 44080 44081 this.i18n = null; // reset local i18n context 44082 } 44083 44084 i18nAttributesInstruction(nodeIndex, attrs, sourceSpan) { 44085 let hasBindings = false; 44086 const i18nAttrArgs = []; 44087 attrs.forEach(attr => { 44088 const message = attr.i18n; 44089 const converted = attr.value.visit(this._valueConverter); 44090 this.allocateBindingSlots(converted); 44091 44092 if (converted instanceof Interpolation) { 44093 const placeholders = assembleBoundTextPlaceholders(message); 44094 const params = placeholdersToParams(placeholders); 44095 i18nAttrArgs.push(literal(attr.name), this.i18nTranslate(message, params)); 44096 converted.expressions.forEach(expression => { 44097 hasBindings = true; 44098 this.updateInstructionWithAdvance(nodeIndex, sourceSpan, Identifiers.i18nExp, () => this.convertPropertyBinding(expression)); 44099 }); 44100 } 44101 }); 44102 44103 if (i18nAttrArgs.length > 0) { 44104 const index = literal(this.allocateDataSlot()); 44105 const constIndex = this.addToConsts(literalArr(i18nAttrArgs)); 44106 this.creationInstruction(sourceSpan, Identifiers.i18nAttributes, [index, constIndex]); 44107 44108 if (hasBindings) { 44109 this.updateInstruction(sourceSpan, Identifiers.i18nApply, [index]); 44110 } 44111 } 44112 } 44113
44114 getNamespaceInstruction(namespaceKey) { 44115 switch (namespaceKey) { 44116 case 'math': 44117 return Identifiers.namespaceMathML; 44118 44119 case 'svg': 44120 return Identifiers.namespaceSVG; 44121 44122 default: 44123 return Identifiers.namespaceHTML; 44124 } 44125 } 44126 44127 addNamespaceInstruction(nsInstruction, element) { 44128 this._namespace = nsInstruction; 44129 this.creationInstruction(element.startSourceSpan, nsInstruction); 44130 } 44131 /** 44132 * Adds an update instruction for an interpolated property or attribute, such as 44133 * `prop="{{value}}"` or `attr.title="{{value}}"` 44134 */ 44135 44136 44137 interpolatedUpdateInstruction(instruction, elementIndex, attrName, input, value, params) { 44138 this.updateInstructionWithAdvance(elementIndex, input.sourceSpan, instruction, () => [literal(attrName), ...this.getUpdateInstructionArguments(value), ...params]); 44139 } 44140 44141 visitContent(ngContent) { 44142 const slot = this.allocateDataSlot(); 44143 const projectionSlotIdx = this._ngContentSelectorsOffset + this._ngContentReservedSlots.length; 44144 const parameters = [literal(slot)]; 44145 44146 this._ngContentReservedSlots.push(ngContent.selector); 44147 44148 const nonContentSelectAttributes = ngContent.attributes.filter(attr => attr.name.toLowerCase() !== NG_CONTENT_SELECT_ATTR); 44149 const attributes = this.getAttributeExpressions(ngContent.name, nonContentSelectAttributes, [], []); 44150 44151 if (attributes.length > 0) { 44152 parameters.push(literal(projectionSlotIdx), literalArr(attributes)); 44153 } else if (projectionSlotIdx !== 0) { 44154 parameters.push(literal(projectionSlotIdx)); 44155 } 44156 44157 this.creationInstruction(ngContent.sourceSpan, Identifiers.projection, parameters); 44158 44159 if (this.i18n) { 44160 this.i18n.appendProjection(ngContent.i18n, slot); 44161 } 44162 } 44163 44164 visitElement(element) { 44165 const elementIndex = this.allocateDataSlot(); 44166 const stylingBuilder = new StylingBuilder(null); 44167 let isNonBindableMode = false; 44168 const isI18nRootElement = isI18nRootNode(element.i18n) && !isSingleI18nIcu(element.i18n); 44169 const outputAttrs = []; 44170 const [namespaceKey, elementName] = splitNsName(element.name); 44171 const isNgContainer$1 = isNgContainer(element.name); // Handle styling, i18n, ngNonBindable attributes 44172 44173 for (const attr of element.attributes) { 44174 const { 44175 name, 44176 value 44177 } = attr; 44178 44179 if (name === NON_BINDABLE_ATTR) { 44180 isNonBindableMode = true; 44181 } else if (name === 'style') { 44182 stylingBuilder.registerStyleAttr(value); 44183 } else if (name === 'class') { 44184 stylingBuilder.registerClassAttr(value); 44185 } else { 44186 outputAttrs.push(attr); 44187 } 44188 } // Regular element or ng-container creation mode 44189 44190 44191 const parameters = [literal(elementIndex)]; 44192 44193 if (!isNgContainer$1) { 44194 parameters.push(literal(elementName)); 44195 } // Add the attributes 44196 44197 44198 const allOtherInputs = []; 44199 const boundI18nAttrs = []; 44200 element.inputs.forEach(input => { 44201 const stylingInputWasSet = stylingBuilder.registerBoundInput(input); 44202 44203 if (!stylingInputWasSet) { 44204 if (input.type === 0 44205 /* BindingType.Property */ 44206 && input.i18n) { 44207 boundI18nAttrs.push(input); 44208 } else { 44209 allOtherInputs.push(input); 44210 } 44211 } 44212 }); // add attributes for directive and projection matching purposes 44213 44214 const attributes = this.getAttributeExpressions(element.name, outputAttrs, allOtherInputs, element.outputs, stylingBuilder, [], boundI18nAttrs); 44215 parameters.push(this.addAttrsToConsts(attributes)); // local refs (ex.: <div #foo #bar="baz">) 44216 44217 const refs = this.prepareRefsArray(element.references); 44218 parameters.push(this.addToConsts(refs)); 44219 const wasInNamespace = this._namespace; 44220 const currentNamespace = this.getNamespaceInstruction(namespaceKey); // If the namespace is changing now, include an instruction to change it 44221 // during element creation. 44222 44223 if (currentNamespace !== wasInNamespace) { 44224 this.addNamespaceInstruction(currentNamespace, element); 44225 } 44226 44227 if (this.i18n) { 44228 this.i18n.appendElement(element.i18n, elementIndex); 44229 } // Note that we do not append text node instructions and ICUs inside i18n section, 44230 // so we exclude them while calculating whether current element has children 44231 44232 44233 const hasChildren = !isI18nRootElement && this.i18n ? !hasTextChildrenOnly(element.children) : element.children.length > 0; 44234 const createSelfClosingInstruction = !stylingBuilder.hasBindingsWithPipes && element.outputs.length === 0 && boundI18nAttrs.length === 0 && !hasChildren; 44235 const createSelfClosingI18nInstruction = !createSelfClosingInstruction && hasTextChildrenOnly(element.children); 44236 44237 if (createSelfClosingInstruction) { 44238 this.creationInstruction(element.sourceSpan, isNgContainer$1 ? Identifiers.elementContainer : Identifiers.element, trimTrailingNulls(parameters)); 44239 } else { 44240 this.creationInstruction(element.startSourceSpan, isNgContainer$1 ? Identifiers.elementContainerStart : Identifiers.elementStart, trimTrailingNulls(parameters)); 44241 44242 if (isNonBindableMode) { 44243 this.creationInstruction(element.startSourceSpan, Identifiers.disableBindings); 44244 } 44245 44246 if (boundI18nAttrs.length > 0) { 44247 this.i18nAttributesInstruction(elementIndex, boundI18nAttrs, element.startSourceSpan ?? element.sourceSpan); 44248 } // Generate Listeners (outputs) 44249 44250 44251 if (element.outputs.length > 0) { 44252 for (const outputAst of element.outputs) { 44253 this.creationInstruction(outputAst.sourceSpan, Identifiers.listener, this.prepareListenerParameter(element.name, outputAst, elementIndex)); 44254 } 44255 } // Note: it's important to keep i18n/i18nStart instructions after i18nAttributes and 44256 // listeners, to make sure i18nAttributes instruction targets current element at runtime. 44257 44258 44259 if (isI18nRootElement) { 44260 this.i18nStart(element.startSourceSpan, element.i18n, createSelfClosingI18nInstruction); 44261 } 44262 } // the code here will collect all update-level styling instructions and add them to the 44263 // update block of the template function AOT code. Instructions like `styleProp`, 44264 // `styleMap`, `classMap`, `classProp` 44265 // are all generated and assigned in the code below. 44266 44267 44268 const stylingInstructions = stylingBuilder.buildUpdateLevelInstructions(this._valueConverter); 44269 const limit = stylingInstructions.length - 1; 44270 44271 for (let i = 0; i <= limit; i++) { 44272 const instruction = stylingInstructions[i]; 44273 this._bindingSlots += this.processStylingUpdateInstruction(elementIndex, instruction); 44274 } // the reason why `undefined` is used is because the renderer understands this as a 44275 // special value to symbolize that there is no RHS to this binding 44276 // TODO (matsko): revisit this once FW-959 is approached 44277 44278 44279 const emptyValueBindInstruction = literal(undefined); 44280 const propertyBindings = []; 44281 const attributeBindings = []; // Generate element input bindings 44282
44283 allOtherInputs.forEach(input => { 44284 const inputType = input.type; 44285 44286 if (inputType === 4 44287 /* BindingType.Animation */ 44288 ) { 44289 const value = input.value.visit(this._valueConverter); // animation bindings can be presented in the following formats: 44290 // 1. [@binding]="fooExp" 44291 // 2. [@binding]="{value:fooExp, params:{...}}" 44292 // 3. [@binding] 44293 // 4. @binding 44294 // All formats will be valid for when a synthetic binding is created. 44295 // The reasoning for this is because the renderer should get each 44296 // synthetic binding value in the order of the array that they are 44297 // defined in... 44298 44299 const hasValue = value instanceof LiteralPrimitive ? !!value.value : true; 44300 this.allocateBindingSlots(value); 44301 propertyBindings.push({ 44302 span: input.sourceSpan, 44303 paramsOrFn: getBindingFunctionParams(() => hasValue ? this.convertPropertyBinding(value) : emptyValueBindInstruction, prepareSyntheticPropertyName(input.name)) 44304 }); 44305 } else { 44306 // we must skip attributes with associated i18n context, since these attributes are handled 44307 // separately and corresponding `i18nExp` and `i18nApply` instructions will be generated 44308 if (input.i18n) return; 44309 const value = input.value.visit(this._valueConverter); 44310 44311 if (value !== undefined) { 44312 const params = []; 44313 const [attrNamespace, attrName] = splitNsName(input.name); 44314 const isAttributeBinding = inputType === 1 44315 /* BindingType.Attribute */ 44316 ; 44317 const sanitizationRef = resolveSanitizationFn(input.securityContext, isAttributeBinding); 44318 if (sanitizationRef) params.push(sanitizationRef); 44319 44320 if (attrNamespace) { 44321 const namespaceLiteral = literal(attrNamespace); 44322 44323 if (sanitizationRef) { 44324 params.push(namespaceLiteral); 44325 } else { 44326 // If there wasn't a sanitization ref, we need to add 44327 // an extra param so that we can pass in the namespace. 44328 params.push(literal(null), namespaceLiteral); 44329 } 44330 } 44331 44332 this.allocateBindingSlots(value); 44333 44334 if (inputType === 0 44335 /* BindingType.Property */ 44336 ) { 44337 if (value instanceof Interpolation) { 44338 // prop="{{value}}" and friends 44339 this.interpolatedUpdateInstruction(getPropertyInterpolationExpression(value), elementIndex, attrName, input, value, params); 44340 } else { 44341 // [prop]="value" 44342 // Collect all the properties so that we can chain into a single function at the end. 44343 propertyBindings.push({ 44344 span: input.sourceSpan, 44345 paramsOrFn: getBindingFunctionParams(() => this.convertPropertyBinding(value), attrName, params) 44346 }); 44347 } 44348 } else if (inputType === 1 44349 /* BindingType.Attribute */ 44350 ) { 44351 if (value instanceof Interpolation && getInterpolationArgsLength(value) > 1) { 44352 // attr.name="text{{value}}" and friends 44353 this.interpolatedUpdateInstruction(getAttributeInterpolationExpression(value), elementIndex, attrName, input, value, params); 44354 } else { 44355 const boundValue = value instanceof Interpolation ? value.expressions[0] : value; // [attr.name]="value" or attr.name="{{value}}" 44356 // Collect the attribute bindings so that they can be chained at the end. 44357 44358 attributeBindings.push({ 44359 span: input.sourceSpan, 44360 paramsOrFn: getBindingFunctionParams(() => this.convertPropertyBinding(boundValue), attrName, params) 44361 }); 44362 } 44363 } else { 44364 // class prop 44365 this.updateInstructionWithAdvance(elementIndex, input.sourceSpan, Identifiers.classProp, () => { 44366 return [literal(elementIndex), literal(attrName), this.convertPropertyBinding(value), ...params]; 44367 }); 44368 } 44369 } 44370 } 44371 }); 44372 44373 for (const propertyBinding of propertyBindings) { 44374 this.updateInstructionWithAdvance(elementIndex, propertyBinding.span, Identifiers.property, propertyBinding.paramsOrFn); 44375 } 44376 44377 for (const attributeBinding of attributeBindings) { 44378 this.updateInstructionWithAdvance(elementIndex, attributeBinding.span, Identifiers.attribute, attributeBinding.paramsOrFn); 44379 } // Traverse element child nodes 44380 44381 44382 visitAll$1(this, element.children); 44383
44384 if (!isI18nRootElement && this.i18n) { 44385 this.i18n.appendElement(element.i18n, elementIndex, true); 44386 } 44387 44388 if (!createSelfClosingInstruction) { 44389 // Finish element construction mode. 44390 const span = element.endSourceSpan ?? element.sourceSpan; 44391 44392 if (isI18nRootElement) { 44393 this.i18nEnd(span, createSelfClosingI18nInstruction); 44394 } 44395 44396 if (isNonBindableMode) { 44397 this.creationInstruction(span, Identifiers.enableBindings); 44398 } 44399 44400 this.creationInstruction(span, isNgContainer$1 ? Identifiers.elementContainerEnd : Identifiers.elementEnd); 44401 } 44402 } 44403 44404 visitTemplate(template) { 44405 const NG_TEMPLATE_TAG_NAME = 'ng-template'; 44406 const templateIndex = this.allocateDataSlot(); 44407 44408 if (this.i18n) { 44409 this.i18n.appendTemplate(template.i18n, templateIndex); 44410 } 44411 44412 const tagNameWithoutNamespace = template.tagName ? splitNsName(template.tagName)[1] : template.tagName; 44413 const contextName = `${this.contextName}${template.tagName ? '_' + sanitizeIdentifier(template.tagName) : ''}_${templateIndex}`; 44414 const templateName = `${contextName}_Template`; 44415 const parameters = [literal(templateIndex), variable(templateName), // We don't care about the tag's namespace here, because we infer 44416 // it based on the parent nodes inside the template instruction. 44417 literal(tagNameWithoutNamespace)]; // prepare attributes parameter (including attributes used for directive matching) 44418 44419 const attrsExprs = this.getAttributeExpressions(NG_TEMPLATE_TAG_NAME, template.attributes, template.inputs, template.outputs, undefined 44420 /* styles */ 44421 , template.templateAttrs); 44422 parameters.push(this.addAttrsToConsts(attrsExprs)); // local refs (ex.: <ng-template #foo>) 44423 44424 if (template.references && template.references.length) { 44425 const refs = this.prepareRefsArray(template.references); 44426 parameters.push(this.addToConsts(refs)); 44427 parameters.push(importExpr(Identifiers.templateRefExtractor)); 44428 } // Create the template function 44429 44430 44431 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 44432 // processing, so they are queued here until after the initial pass. Otherwise, we wouldn't 44433 // be able to support bindings in nested templates to local refs that occur after the 44434 // template definition. e.g. <div *ngIf="showing">{{ foo }}</div> <div #foo></div> 44435 44436 this._nestedTemplateFns.push(() => { 44437 const templateFunctionExpr = templateVisitor.buildTemplateFunction(template.children, template.variables, this._ngContentReservedSlots.length + this._ngContentSelectorsOffset, template.i18n); 44438 this.constantPool.statements.push(templateFunctionExpr.toDeclStmt(templateName)); 44439 44440 if (templateVisitor._ngContentReservedSlots.length) { 44441 this._ngContentReservedSlots.push(...templateVisitor._ngContentReservedSlots); 44442 } 44443 }); // e.g. template(1, MyComp_Template_1) 44444 44445 44446 this.creationInstruction(template.sourceSpan, Identifiers.templateCreate, () => { 44447 parameters.splice(2, 0, literal(templateVisitor.getConstCount()), literal(templateVisitor.getVarCount())); 44448 return trimTrailingNulls(parameters); 44449 }); // handle property bindings e.g. ɵɵproperty('ngForOf', ctx.items), et al; 44450 44451 this.templatePropertyBindings(templateIndex, template.templateAttrs); // Only add normal input/output binding instructions on explicit <ng-template> elements. 44452 44453 if (tagNameWithoutNamespace === NG_TEMPLATE_TAG_NAME) { 44454 const [i18nInputs, inputs] = partitionArray(template.inputs, hasI18nMeta); // Add i18n attributes that may act as inputs to directives. If such attributes are present, 44455 // generate `i18nAttributes` instruction. Note: we generate it only for explicit <ng-template> 44456 // elements, in case of inline templates, corresponding instructions will be generated in the 44457 // nested template function. 44458 44459 if (i18nInputs.length > 0) { 44460 this.i18nAttributesInstruction(templateIndex, i18nInputs, template.startSourceSpan ?? template.sourceSpan); 44461 } // Add the input bindings 44462 44463 44464 if (inputs.length > 0) { 44465 this.templatePropertyBindings(templateIndex, inputs); 44466 } // Generate listeners for directive output 44467 44468 44469 for (const outputAst of template.outputs) { 44470 this.creationInstruction(outputAst.sourceSpan, Identifiers.listener, this.prepareListenerParameter('ng_template', outputAst, templateIndex)); 44471 } 44472 } 44473 } 44474 44475 visitBoundText(text) { 44476 if (this.i18n) { 44477 const value = text.value.visit(this._valueConverter); 44478 this.allocateBindingSlots(value); 44479 44480 if (value instanceof Interpolation) { 44481 this.i18n.appendBoundText(text.i18n); 44482 this.i18nAppendBindings(value.expressions); 44483 } 44484 44485 return; 44486 } 44487 44488 const nodeIndex = this.allocateDataSlot(); 44489 this.creationInstruction(text.sourceSpan, Identifiers.text, [literal(nodeIndex)]); 44490 const value = text.value.visit(this._valueConverter); 44491 this.allocateBindingSlots(value); 44492 44493 if (value instanceof Interpolation) { 44494 this.updateInstructionWithAdvance(nodeIndex, text.sourceSpan, getTextInterpolationExpression(value), () => this.getUpdateInstructionArguments(value)); 44495 } else { 44496 error('Text nodes should be interpolated and never bound directly.'); 44497 } 44498 } 44499 44500 visitText(text) { 44501 // when a text element is located within a translatable 44502 // block, we exclude this text element from instructions set, 44503 // since it will be captured in i18n content and processed at runtime 44504 if (!this.i18n) { 44505 this.creationInstruction(text.sourceSpan, Identifiers.text, [literal(this.allocateDataSlot()), literal(text.value)]); 44506 } 44507 } 44508 44509 visitIcu(icu) { 44510 let initWasInvoked = false; // if an ICU was created outside of i18n block, we still treat 44511 // it as a translatable entity and invoke i18nStart and i18nEnd 44512 // to generate i18n context and the necessary instructions 44513 44514 if (!this.i18n) { 44515 initWasInvoked = true; 44516 this.i18nStart(null, icu.i18n, true); 44517 } 44518 44519 const i18n = this.i18n;
44520 const vars = this.i18nBindProps(icu.vars); 44521 const placeholders = this.i18nBindProps(icu.placeholders); // output ICU directly and keep ICU reference in context 44522 44523 const message = icu.i18n; // we always need post-processing function for ICUs, to make sure that: 44524 // - all placeholders in a form of {PLACEHOLDER} are replaced with actual values (note: 44525 // `goog.getMsg` does not process ICUs and uses the `{PLACEHOLDER}` format for placeholders 44526 // inside ICUs) 44527 // - all ICU vars (such as `VAR_SELECT` or `VAR_PLURAL`) are replaced with correct values 44528 44529 const transformFn = raw => { 44530 const params = { ...vars, 44531 ...placeholders 44532 }; 44533 const formatted = formatI18nPlaceholderNamesInMap(params, 44534 /* useCamelCase */ 44535 false); 44536 return invokeInstruction(null, Identifiers.i18nPostprocess, [raw, mapLiteral(formatted, true)]); 44537 }; // in case the whole i18n message is a single ICU - we do not need to 44538 // create a separate top-level translation, we can use the root ref instead 44539 // and make this ICU a top-level translation 44540 // note: ICU placeholders are replaced with actual values in `i18nPostprocess` function 44541 // separately, so we do not pass placeholders into `i18nTranslate` function. 44542 44543 44544 if (isSingleI18nIcu(i18n.meta)) { 44545 this.i18nTranslate(message, 44546 /* placeholders */ 44547 {}, i18n.ref, transformFn); 44548 } else { 44549 // output ICU directly and keep ICU reference in context 44550 const ref = this.i18nTranslate(message, 44551 /* placeholders */ 44552 {}, 44553 /* ref */ 44554 undefined, transformFn); 44555 i18n.appendIcu(icuFromI18nMessage(message).name, ref); 44556 } 44557 44558 if (initWasInvoked) { 44559 this.i18nEnd(null, true); 44560 } 44561 44562 return null; 44563 } 44564 44565 allocateDataSlot() { 44566 return this._dataIndex++; 44567 } 44568 44569 getConstCount() { 44570 return this._dataIndex; 44571 } 44572 44573 getVarCount() { 44574 return this._pureFunctionSlots; 44575 } 44576 44577 getConsts() { 44578 return this._constants; 44579 } 44580 44581 getNgContentSelectors() { 44582 return this._ngContentReservedSlots.length ? this.constantPool.getConstLiteral(asLiteral(this._ngContentReservedSlots), true) : null; 44583 } 44584 44585 bindingContext() { 44586 return `${this._bindingContext++}`; 44587 } 44588 44589 templatePropertyBindings(templateIndex, attrs) { 44590 const propertyBindings = []; 44591 44592 for (const input of attrs) { 44593 if (!(input instanceof BoundAttribute)) { 44594 continue; 44595 } 44596 44597 const value = input.value.visit(this._valueConverter); 44598 44599 if (value === undefined) { 44600 continue; 44601 } 44602 44603 this.allocateBindingSlots(value); 44604 44605 if (value instanceof Interpolation) { 44606 // Params typically contain attribute namespace and value sanitizer, which is applicable 44607 // for regular HTML elements, but not applicable for <ng-template> (since props act as 44608 // inputs to directives), so keep params array empty. 44609 const params = []; // prop="{{value}}" case 44610 44611 this.interpolatedUpdateInstruction(getPropertyInterpolationExpression(value), templateIndex, input.name, input, value, params); 44612 } else { 44613 // [prop]="value" case 44614 propertyBindings.push({ 44615 span: input.sourceSpan, 44616 paramsOrFn: getBindingFunctionParams(() => this.convertPropertyBinding(value), input.name) 44617 }); 44618 } 44619 } 44620 44621 for (const propertyBinding of propertyBindings) { 44622 this.updateInstructionWithAdvance(templateIndex, propertyBinding.span, Identifiers.property, propertyBinding.paramsOrFn); 44623 } 44624 } // Bindings must only be resolved after all local refs have been visited, so all 44625 // instructions are queued in callbacks that execute once the initial pass has completed. 44626 // Otherwise, we wouldn't be able to support local refs that are defined after their 44627 // bindings. e.g. {{ foo }} <div #foo></div> 44628 44629 44630 instructionFn(fns, span, reference, paramsOrFn, prepend = false) { 44631 fns[prepend ? 'unshift' : 'push']({ 44632 span, 44633 reference, 44634 paramsOrFn 44635 }); 44636 } 44637 44638 processStylingUpdateInstruction(elementIndex, instruction) { 44639 let allocateBindingSlots = 0; 44640 44641 if (instruction) { 44642 for (const call of instruction.calls) { 44643 allocateBindingSlots += call.allocateBindingSlots; 44644 this.updateInstructionWithAdvance(elementIndex, call.sourceSpan, instruction.reference, () => call.params(value =>
44644 call.supportsInterpolation && value instanceof Interpolation ? this.getUpdateInstructionArguments(value) : this.convertPropertyBinding(value))); 44645 } 44646 } 44647 44648 return allocateBindingSlots; 44649 } 44650 44651 creationInstruction(span, reference, paramsOrFn, prepend) { 44652 this.instructionFn(this._creationCodeFns, span, reference, paramsOrFn || [], prepend); 44653 } 44654 44655 updateInstructionWithAdvance(nodeIndex, span, reference, paramsOrFn) { 44656 this.addAdvanceInstructionIfNecessary(nodeIndex, span); 44657 this.updateInstruction(span, reference, paramsOrFn); 44658 } 44659 44660 updateInstruction(span, reference, paramsOrFn) { 44661 this.instructionFn(this._updateCodeFns, span, reference, paramsOrFn || []); 44662 } 44663 44664 addAdvanceInstructionIfNecessary(nodeIndex, span) { 44665 if (nodeIndex !== this._currentIndex) { 44666 const delta = nodeIndex - this._currentIndex; 44667 44668 if (delta < 1) { 44669 throw new Error('advance instruction can only go forwards'); 44670 } 44671 44672 this.instructionFn(this._updateCodeFns, span, Identifiers.advance, [literal(delta)]); 44673 this._currentIndex = nodeIndex; 44674 } 44675 } 44676 44677 allocatePureFunctionSlots(numSlots) { 44678 const originalSlots = this._pureFunctionSlots; 44679 this._pureFunctionSlots += numSlots; 44680 return originalSlots; 44681 } 44682 44683 allocateBindingSlots(value) { 44684 this._bindingSlots += value instanceof Interpolation ? value.expressions.length : 1; 44685 } 44686 /** 44687 * Gets an expression that refers to the implicit receiver. The implicit 44688 * receiver is always the root level context. 44689 */ 44690 44691 44692 getImplicitReceiverExpr() { 44693 if (this._implicitReceiverExpr) { 44694 return this._implicitReceiverExpr; 44695 } 44696 44697 return this._implicitReceiverExpr = this.level === 0 ? variable(CONTEXT_NAME) : this._bindingScope.getOrCreateSharedContextVar(0); 44698 } 44699 44700 convertPropertyBinding(value) { 44701 const convertedPropertyBinding = convertPropertyBinding(this, this.getImplicitReceiverExpr(), value, this.bindingContext()); 44702 const valExpr = convertedPropertyBinding.currValExpr; 44703 44704 this._tempVariables.push(...convertedPropertyBinding.stmts); 44705 44706 return valExpr; 44707 } 44708 /** 44709 * Gets a list of argument expressions to pass to an update instruction expression. Also updates 44710 * the temp variables state with temp variables that were identified as needing to be created 44711 * while visiting the arguments. 44712 * @param value The original expression we will be resolving an arguments list from. 44713 */ 44714 44715 44716 getUpdateInstructionArguments(value) { 44717 const { 44718 args, 44719 stmts 44720 } = convertUpdateArguments(this, this.getImplicitReceiverExpr(), value, this.bindingContext()); 44721 44722 this._tempVariables.push(...stmts); 44723 44724 return args; 44725 } 44726 /** 44727 * Prepares all attribute expression values for the `TAttributes` array. 44728 * 44729 * The purpose of this function is to properly construct an attributes array that 44730 * is passed into the `elementStart` (or just `element`) functions. Because there 44731 * are many different types of attributes, the array needs to be constructed in a 44732 * special way so that `elementStart` can properly evaluate them. 44733 * 44734 * The format looks like this: 44735 * 44736 * ``` 44737 * attrs = [prop, value, prop2, value2, 44738 * PROJECT_AS, selector, 44739 * CLASSES, class1, class2, 44740 * STYLES, style1, value1, style2, value2, 44741 * BINDINGS, name1, name2, name3, 44742 * TEMPLATE, name4, name5, name6, 44743 * I18N, name7, name8, ...] 44744 * ``` 44745 * 44746 * Note that this function will fully ignore all synthetic (@foo) attribute values 44747 * because those values are intended to always be generated as property instructions. 44748 */ 44749 44750 44751 getAttributeExpressions(elementName, renderAttributes, inputs, outputs, styles, templateAttrs = [], boundI18nAttrs = []) { 44752 const alreadySeen = new Set(); 44753 const attrExprs = []; 44754 let ngProjectAsAttr; 44755 44756 for (const attr of renderAttributes) { 44757 if (attr.name === NG_PROJECT_AS_ATTR_NAME) { 44758 ngProjectAsAttr = attr; 44759 } // Note that static i18n attributes aren't in the i18n array, 44760 // because they're treated in the same way as regular attributes. 44761 44762 44763 if (attr.i18n) { 44764 // When i18n attributes are present on elements with structural directives 44765 // (e.g. `<div *ngIf title="Hello" i18n-title>`), we want to avoid generating 44766 // duplicate i18n translation blocks for `ɵɵtemplate` and `ɵɵelement` instruction 44767 // attributes. So we do a cache lookup to see if suitable i18n translation block 44768 // already exists. 44769 const { 44770 i18nVarRefsCache 44771 } = this._constants; 44772 let i18nVarRef; 44773 44774 if (i18nVarRefsCache.has(attr.i18n)) { 44775 i18nVarRef = i18nVarRefsCache.get(attr.i18n); 44776 } else { 44777 i18nVarRef = this.i18nTranslate(attr.i18n); 44778 i18nVarRefsCache.set(attr.i18n, i18nVarRef); 44779 } 44780
44781 attrExprs.push(literal(attr.name), i18nVarRef); 44782 } else { 44783 attrExprs.push(...getAttributeNameLiterals(attr.name), trustedConstAttribute(elementName, attr)); 44784 } 44785 } // Keep ngProjectAs next to the other name, value pairs so we can verify that we match 44786 // ngProjectAs marker in the attribute name slot. 44787 44788 44789 if (ngProjectAsAttr) { 44790 attrExprs.push(...getNgProjectAsLiteral(ngProjectAsAttr)); 44791 } 44792 44793 function addAttrExpr(key, value) { 44794 if (typeof key === 'string') { 44795 if (!alreadySeen.has(key)) { 44796 attrExprs.push(...getAttributeNameLiterals(key)); 44797 value !== undefined && attrExprs.push(value); 44798 alreadySeen.add(key); 44799 } 44800 } else { 44801 attrExprs.push(literal(key)); 44802 } 44803 } // it's important that this occurs before BINDINGS and TEMPLATE because once `elementStart` 44804 // comes across the BINDINGS or TEMPLATE markers then it will continue reading each value as 44805 // as single property value cell by cell. 44806 44807 44808 if (styles) { 44809 styles.populateInitialStylingAttrs(attrExprs); 44810 } 44811 44812 if (inputs.length || outputs.length) { 44813 const attrsLengthBeforeInputs = attrExprs.length; 44814 44815 for (let i = 0; i < inputs.length; i++) { 44816 const input = inputs[i]; // We don't want the animation and attribute bindings in the 44817 // attributes array since they aren't used for directive matching. 44818 44819 if (input.type !== 4 44820 /* BindingType.Animation */ 44821 && input.type !== 1 44822 /* BindingType.Attribute */ 44823 ) { 44824 addAttrExpr(input.name); 44825 } 44826 } 44827 44828 for (let i = 0; i < outputs.length; i++) { 44829 const output = outputs[i]; 44830 44831 if (output.type !== 1 44832 /* ParsedEventType.Animation */ 44833 ) { 44834 addAttrExpr(output.name); 44835 } 44836 } // this is a cheap way of adding the marker only after all the input/output 44837 // values have been filtered (by not including the animation ones) and added 44838 // to the expressions. The marker is important because it tells the runtime 44839 // code that this is where attributes without values start... 44840 44841 44842 if (attrExprs.length !== attrsLengthBeforeInputs) { 44843 attrExprs.splice(attrsLengthBeforeInputs, 0, literal(3 44844 /* core.AttributeMarker.Bindings */ 44845 )); 44846 } 44847 } 44848 44849 if (templateAttrs.length) { 44850 attrExprs.push(literal(4 44851 /* core.AttributeMarker.Template */ 44852 )); 44853 templateAttrs.forEach(attr => addAttrExpr(attr.name)); 44854 } 44855 44856 if (boundI18nAttrs.length) { 44857 attrExprs.push(literal(6 44858 /* core.AttributeMarker.I18n */ 44859 )); 44860 boundI18nAttrs.forEach(attr => addAttrExpr(attr.name)); 44861 } 44862 44863 return attrExprs; 44864 } 44865 44866 addToConsts(expression) { 44867 if (isNull(expression)) { 44868 return TYPED_NULL_EXPR; 44869 } 44870 44871 const consts = this._constants.constExpressions; // Try to reuse a literal that's already in the array, if possible. 44872 44873 for (let i = 0; i < consts.length; i++) { 44874 if (consts[i].isEquivalent(expression)) { 44875 return literal(i); 44876 } 44877 } 44878 44879 return literal(consts.push(expression) - 1); 44880 } 44881 44882 addAttrsToConsts(attrs) { 44883 return attrs.length > 0 ? this.addToConsts(literalArr(attrs)) : TYPED_NULL_EXPR; 44884 } 44885 44886 prepareRefsArray(references) { 44887 if (!references || references.length === 0) { 44888 return TYPED_NULL_EXPR; 44889 } 44890 44891 const refsParam = flatten(references.map(reference => { 44892 const slot = this.allocateDataSlot(); // Generate the update temporary. 44893 44894 const variableName = this._bindingScope.freshReferenceName(); 44895 44896 const retrievalLevel = this.level; 44897 const lhs = variable(variableName); 44898 44899 this._bindingScope.set(retrievalLevel, reference.name, lhs, 0 44900 /* DeclarationPriority.DEFAULT */ 44901 , (scope, relativeLevel) => { 44902 // e.g. nextContext(2); 44903 const nextContextStmt = relativeLevel > 0 ? [generateNextContextExpr(relativeLevel).toStmt()] : []; // e.g. const $foo$ = reference(1); 44904 44905 const refExpr = lhs.set(importExpr(Identifiers.reference).callFn([literal(slot)])); 44906 return nextContextStmt.concat(refExpr.toConstDecl()); 44907 }, true); 44908 44909 return [reference.name, reference.value]; 44910 })); 44911 return asLiteral(refsParam); 44912 } 44913 44914 prepareListenerParameter(tagName, outputAst, index) { 44915 return () => { 44916 const eventName = outputAst.name; 44917 const bindingFnName = outputAst.type === 1 44918 /* ParsedEventType.Animation */ 44919 ? // synthetic @listener.foo values are treated the exact same as are standard listeners 44920 prepareSyntheticListenerFunctionName(eventName, outputAst.phase) : sanitizeIdentifier(eventName); 44921 const handlerName = `${this.templateName}_${tagName}_${bindingFnName}_${index}_listener`; 44922 44923 const scope = this._bindingScope.nestedScope(this._bindingScope.bindingLevel, EVENT_BINDING_SCOPE_GLOBALS); 44924 44925 return prepareEventListenerParameters(outputAst, handlerName, scope); 44926 }; 44927 } 44928 44929} 44930 44931class ValueConverter extends AstMemoryEfficientTransformer { 44932 constructor(constantPool, allocateSlot, allocatePureFunctionSlots, definePipe) { 44933 super(); 44934 this.constantPool = constantPool; 44935 this.allocateSlot = allocateSlot; 44936 this.allocatePureFunctionSlots = allocatePureFunctionSlots; 44937 this.definePipe = definePipe; 44938 this._pipeBindExprs = []; 44939 } // AstMemoryEfficientTransformer 44940 44941 44942 visitPipe(pipe, context) { 44943 // Allocate a slot to create the pipe 44944 const slot = this.allocateSlot(); 44945 const slotPseudoLocal = `PIPE:${slot}`; // Allocate one slot for the result plus one slot per pipe argument 44946 44947 const pureFunctionSlot = this.allocatePureFunctionSlots(2 + pipe.args.length); 44948 const target = new PropertyRead(pipe.span, pipe.sourceSpan, pipe.nameSpan, new ImplicitReceiver(pipe.span, pipe.sourceSpan), slotPseudoLocal); 44949 const { 44950 identifier, 44951 isVarLength 44952 } = pipeBindingCallInfo(pipe.args); 44953 this.definePipe(pipe.name, slotPseudoLocal, slot, importExpr(identifier)); 44954 const args = [pipe.exp, ...pipe.args]; 44955 const convertedArgs = isVarLength ? this.visitAll([new LiteralArray(pipe.span, pipe.sourceSpan, args)]) : this.visitAll(args); 44956 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); 44957 44958 this._pipeBindExprs.push(pipeBindExpr); 44959 44960 return pipeBindExpr; 44961 } 44962 44963 updatePipeSlotOffsets(bindingSlots) {
44964 this._pipeBindExprs.forEach(pipe => { 44965 // update the slot offset arg (index 1) to account for binding slots 44966 const slotOffset = pipe.args[1]; 44967 slotOffset.value += bindingSlots; 44968 }); 44969 } 44970 44971 visitLiteralArray(array, context) { 44972 return new BuiltinFunctionCall(array.span, array.sourceSpan, this.visitAll(array.expressions), values => { 44973 // If the literal has calculated (non-literal) elements transform it into 44974 // calls to literal factories that compose the literal and will cache intermediate 44975 // values. 44976 const literal = literalArr(values); 44977 return getLiteralFactory(this.constantPool, literal, this.allocatePureFunctionSlots); 44978 }); 44979 } 44980 44981 visitLiteralMap(map, context) { 44982 return new BuiltinFunctionCall(map.span, map.sourceSpan, this.visitAll(map.values), values => { 44983 // If the literal has calculated (non-literal) elements transform it into 44984 // calls to literal factories that compose the literal and will cache intermediate 44985 // values. 44986 const literal = literalMap(values.map((value, index) => ({ 44987 key: map.keys[index].key, 44988 value, 44989 quoted: map.keys[index].quoted 44990 }))); 44991 return getLiteralFactory(this.constantPool, literal, this.allocatePureFunctionSlots); 44992 }); 44993 } 44994 44995} // Pipes always have at least one parameter, the value they operate on 44996 44997 44998const pipeBindingIdentifiers = [Identifiers.pipeBind1, Identifiers.pipeBind2, Identifiers.pipeBind3, Identifiers.pipeBind4]; 44999 45000function pipeBindingCallInfo(args) { 45001 const identifier = pipeBindingIdentifiers[args.length]; 45002 return { 45003 identifier: identifier || Identifiers.pipeBindV, 45004 isVarLength: !identifier 45005 }; 45006} 45007 45008const pureFunctionIdentifiers = [Identifiers.pureFunction0, Identifiers.pureFunction1, Identifiers.pureFunction2, Identifiers.pureFunction3, Identifiers.pureFunction4, Identifiers.pureFunction5, Identifiers.pureFunction6, Identifiers.pureFunction7, Identifiers.pureFunction8]; 45009 45010function pureFunctionCallInfo(args) { 45011 const identifier = pureFunctionIdentifiers[args.length]; 45012 return { 45013 identifier: identifier || Identifiers.pureFunctionV, 45014 isVarLength: !identifier 45015 }; 45016} // e.g. x(2); 45017 45018 45019function generateNextContextExpr(relativeLevelDiff) { 45020 return importExpr(Identifiers.nextContext).callFn(relativeLevelDiff > 1 ? [literal(relativeLevelDiff)] : []); 45021} 45022 45023function getLiteralFactory(constantPool, literal$1, allocateSlots) { 45024 const { 45025 literalFactory, 45026 literalFactoryArguments 45027 } = constantPool.getLiteralFactory(literal$1); // Allocate 1 slot for the result plus 1 per argument 45028 45029 const startSlot = allocateSlots(1 + literalFactoryArguments.length); 45030 const { 45031 identifier, 45032 isVarLength 45033 } = pureFunctionCallInfo(literalFactoryArguments); // Literal factories are pure functions that only need to be re-invoked when the parameters 45034 // change. 45035 45036 const args = [literal(startSlot), literalFactory]; 45037 45038 if (isVarLength) { 45039 args.push(literalArr(literalFactoryArguments)); 45040 } else { 45041 args.push(...literalFactoryArguments); 45042 } 45043 45044 return importExpr(identifier).callFn(args); 45045} 45046/** 45047 * Gets an array of literals that can be added to an expression 45048 * to represent the name and namespace of an attribute. E.g. 45049 * `:xlink:href` turns into `[AttributeMarker.NamespaceURI, 'xlink', 'href']`. 45050 * 45051 * @param name Name of the attribute, including the namespace. 45052 */ 45053 45054 45055function getAttributeNameLiterals(name) { 45056 const [attributeNamespace, attributeName] = splitNsName(name); 45057 const nameLiteral = literal(attributeName); 45058 45059 if (attributeNamespace) { 45060 return [literal(0 45061 /* core.AttributeMarker.NamespaceURI */ 45062 ), literal(attributeNamespace), nameLiteral]; 45063 } 45064 45065 return [nameLiteral]; 45066} 45067/** The prefix used to get a shared context in BindingScope's map. */ 45068 45069 45070const SHARED_CONTEXT_KEY = '$$shared_ctx$$'; 45071 45072class BindingScope { 45073 constructor(bindingLevel = 0, parent = null, globals) { 45074 this.bindingLevel = bindingLevel; 45075 this.parent = parent; 45076 this.globals = globals; 45077 /** Keeps a map from local variables to their BindingData. */ 45078 45079 this.map = new Map(); 45080 this.referenceNameIndex = 0; 45081 this.restoreViewVariable = null; 45082 this.usesRestoredViewContext = false;
45083 45084 if (globals !== undefined) { 45085 for (const name of globals) { 45086 this.set(0, name, variable(name)); 45087 } 45088 } 45089 } 45090 45091 static createRootScope() { 45092 return new BindingScope(); 45093 } 45094 45095 get(name) { 45096 let current = this; 45097 45098 while (current) { 45099 let value = current.map.get(name); 45100 45101 if (value != null) { 45102 if (current !== this) { 45103 // make a local copy and reset the `declare` state 45104 value = { 45105 retrievalLevel: value.retrievalLevel, 45106 lhs: value.lhs, 45107 declareLocalCallback: value.declareLocalCallback, 45108 declare: false, 45109 priority: value.priority 45110 }; // Cache the value locally. 45111 45112 this.map.set(name, value); // Possibly generate a shared context var 45113 45114 this.maybeGenerateSharedContextVar(value); 45115 this.maybeRestoreView(); 45116 } 45117 45118 if (value.declareLocalCallback && !value.declare) { 45119 value.declare = true; 45120 } 45121 45122 return value.lhs; 45123 } 45124 45125 current = current.parent; 45126 } // If we get to this point, we are looking for a property on the top level component 45127 // - If level === 0, we are on the top and don't need to re-declare `ctx`. 45128 // - If level > 0, we are in an embedded view. We need to retrieve the name of the 45129 // local var we used to store the component context, e.g. const $comp$ = x(); 45130 45131 45132 return this.bindingLevel === 0 ? null : this.getComponentProperty(name); 45133 } 45134 /** 45135 * Create a local variable for later reference. 45136 * 45137 * @param retrievalLevel The level from which this value can be retrieved 45138 * @param name Name of the variable. 45139 * @param lhs AST representing the left hand side of the `let lhs = rhs;`. 45140 * @param priority The sorting priority of this var 45141 * @param declareLocalCallback The callback to invoke when declaring this local var 45142 * @param localRef Whether or not this is a local ref 45143 */ 45144 45145 45146 set(retrievalLevel, name, lhs, priority = 0 45147 /* DeclarationPriority.DEFAULT */ 45148 , declareLocalCallback, localRef) { 45149 if (this.map.has(name)) { 45150 if (localRef) { 45151 // Do not throw an error if it's a local ref and do not update existing value, 45152 // so the first defined ref is always returned. 45153 return this; 45154 } 45155 45156 error(`The name ${name} is already defined in scope to be ${this.map.get(name)}`); 45157 } 45158 45159 this.map.set(name, { 45160 retrievalLevel: retrievalLevel, 45161 lhs: lhs, 45162 declare: false, 45163 declareLocalCallback: declareLocalCallback, 45164 priority: priority 45165 }); 45166 return this; 45167 } // Implemented as part of LocalResolver. 45168 45169 45170 getLocal(name) { 45171 return this.get(name); 45172 } // Implemented as part of LocalResolver. 45173 45174 45175 notifyImplicitReceiverUse() { 45176 if (this.bindingLevel !== 0) { 45177 // Since the implicit receiver is accessed in an embedded view, we need to 45178 // ensure that we declare a shared context variable for the current template 45179 // in the update variables. 45180 this.map.get(SHARED_CONTEXT_KEY + 0).declare = true; 45181 } 45182 } 45183 45184 nestedScope(level, globals) { 45185 const newScope = new BindingScope(level, this, globals); 45186 if (level > 0) newScope.generateSharedContextVar(0); 45187 return newScope; 45188 } 45189 /** 45190 * Gets or creates a shared context variable and returns its expression. Note that 45191 * this does not mean that the shared variable will be declared. Variables in the 45192 * binding scope will be only declared if they are used. 45193 */ 45194 45195 45196 getOrCreateSharedContextVar(retrievalLevel) { 45197 const bindingKey = SHARED_CONTEXT_KEY + retrievalLevel; 45198 45199 if (!this.map.has(bindingKey)) { 45200 this.generateSharedContextVar(retrievalLevel); 45201 } // Shared context variables are always generated as "ReadVarExpr". 45202 45203 45204 return this.map.get(bindingKey).lhs; 45205 } 45206 45207 getSharedContextName(retrievalLevel) { 45208 const sharedCtxObj = this.map.get(SHARED_CONTEXT_KEY + retrievalLevel); // Shared context variables are always generated as "ReadVarExpr". 45209 45210 return sharedCtxObj && sharedCtxObj.declare ? sharedCtxObj.lhs : null; 45211 } 45212 45213 maybeGenerateSharedContextVar(value) { 45214 if (value.priority === 1 45215 /* DeclarationPriority.CONTEXT */ 45216 && value.retrievalLevel < this.bindingLevel) { 45217 const sharedCtxObj = this.map.get(SHARED_CONTEXT_KEY + value.retrievalLevel); 45218 45219 if (sharedCtxObj) { 45220 sharedCtxObj.declare = true; 45221 } else { 45222 this.generateSharedContextVar(value.retrievalLevel); 45223 } 45224 } 45225 } 45226 45227 generateSharedContextVar(retrievalLevel) { 45228 const lhs = variable(CONTEXT_NAME + this.freshReferenceName()); 45229 this.map.set(SHARED_CONTEXT_KEY + retrievalLevel, { 45230 retrievalLevel: retrievalLevel, 45231 lhs: lhs, 45232 declareLocalCallback: (scope, relativeLevel) => { 45233 // const ctx_r0 = nextContext(2); 45234 return [lhs.set(generateNextContextExpr(relativeLevel)).toConstDecl()]; 45235 }, 45236 declare: false, 45237 priority: 2 45238 /* DeclarationPriority.SHARED_CONTEXT */ 45239 45240 }); 45241 } 45242 45243 getComponentProperty(name) { 45244 const componentValue = this.map.get(SHARED_CONTEXT_KEY + 0); 45245 componentValue.declare = true; 45246 this.maybeRestoreView(); 45247 return componentValue.lhs.prop(name); 45248 } 45249 45250 maybeRestoreView() { 45251 // View restoration is required for listener instructions inside embedded views, because 45252 // they only run in creation mode and they can have references to the context object. 45253 // If the context object changes in update mode, the reference will be incorrect, because 45254 // it was established during creation. 45255 if (this.isListenerScope()) { 45256 if (!this.parent.restoreViewVariable) { 45257 // parent saves variable to generate a shared `const $s$ = getCurrentView();` instruction 45258 this.parent.restoreViewVariable = variable(this.parent.freshReferenceName()); 45259 } 45260 45261 this.restoreViewVariable = this.parent.restoreViewVariable; 45262 } 45263 } 45264
45265 restoreViewStatement() { 45266 if (this.restoreViewVariable) { 45267 const restoreCall = invokeInstruction(null, Identifiers.restoreView, [this.restoreViewVariable]); // Either `const restoredCtx = restoreView($state$);` or `restoreView($state$);` 45268 // depending on whether it is being used. 45269 45270 return this.usesRestoredViewContext ? variable(RESTORED_VIEW_CONTEXT_NAME).set(restoreCall).toConstDecl() : restoreCall.toStmt(); 45271 } 45272 45273 return null; 45274 } 45275 45276 viewSnapshotStatements() { 45277 // const $state$ = getCurrentView(); 45278 return this.restoreViewVariable ? [this.restoreViewVariable.set(invokeInstruction(null, Identifiers.getCurrentView, [])).toConstDecl()] : []; 45279 } 45280 45281 isListenerScope() { 45282 return this.parent && this.parent.bindingLevel === this.bindingLevel; 45283 } 45284 45285 variableDeclarations() { 45286 let currentContextLevel = 0; 45287 return Array.from(this.map.values()).filter(value => value.declare).sort((a, b) => b.retrievalLevel - a.retrievalLevel || b.priority - a.priority).reduce((stmts, value) => { 45288 const levelDiff = this.bindingLevel - value.retrievalLevel; 45289 const currStmts = value.declareLocalCallback(this, levelDiff - currentContextLevel); 45290 currentContextLevel = levelDiff; 45291 return stmts.concat(currStmts); 45292 }, []); 45293 } 45294 45295 freshReferenceName() {
45296 let current = this; // Find the top scope as it maintains the global reference count 45297 45298 while (current.parent) current = current.parent; 45299 45300 const ref = `${REFERENCE_PREFIX}${current.referenceNameIndex++}`; 45301 return ref; 45302 } 45303 45304 hasRestoreViewVariable() { 45305 return !!this.restoreViewVariable; 45306 } 45307 45308 notifyRestoredViewContextUse() { 45309 this.usesRestoredViewContext = true; 45310 } 45311 45312} 45313/** 45314 * Creates a `CssSelector` given a tag name and a map of attributes 45315 */ 45316 45317 45318function createCssSelector(elementName, attributes) { 45319 const cssSelector = new CssSelector(); 45320 const elementNameNoNs = splitNsName(elementName)[1]; 45321 cssSelector.setElement(elementNameNoNs); 45322 Object.getOwnPropertyNames(attributes).forEach(name => { 45323 const nameNoNs = splitNsName(name)[1]; 45324 const value = attributes[name]; 45325 cssSelector.addAttribute(nameNoNs, value); 45326 45327 if (name.toLowerCase() === 'class') { 45328 const classes = value.trim().split(/\s+/); 45329 classes.forEach(className => cssSelector.addClassName(className)); 45330 } 45331 }); 45332 return cssSelector; 45333} 45334/** 45335 * Creates an array of expressions out of an `ngProjectAs` attributes 45336 * which can be added to the instruction parameters. 45337 */ 45338 45339 45340function getNgProjectAsLiteral(attribute) { 45341 // Parse the attribute value into a CssSelectorList. Note that we only take the 45342 // first selector, because we don't support multiple selectors in ngProjectAs. 45343 const parsedR3Selector = parseSelectorToR3Selector(attribute.value)[0]; 45344 return [literal(5 45345 /* core.AttributeMarker.ProjectAs */ 45346 ), asLiteral(parsedR3Selector)]; 45347} 45348/** 45349 * Gets the instruction to generate for an interpolated property 45350 * @param interpolation An Interpolation AST 45351 */ 45352 45353 45354function getPropertyInterpolationExpression(interpolation) { 45355 switch (getInterpolationArgsLength(interpolation)) { 45356 case 1: 45357 return Identifiers.propertyInterpolate; 45358 45359 case 3: 45360 return Identifiers.propertyInterpolate1; 45361 45362 case 5: 45363 return Identifiers.propertyInterpolate2; 45364 45365 case 7: 45366 return Identifiers.propertyInterpolate3; 45367 45368 case 9: 45369 return Identifiers.propertyInterpolate4; 45370 45371 case 11: 45372 return Identifiers.propertyInterpolate5; 45373 45374 case 13: 45375 return Identifiers.propertyInterpolate6; 45376 45377 case 15: 45378 return Identifiers.propertyInterpolate7; 45379 45380 case 17: 45381 return Identifiers.propertyInterpolate8; 45382 45383 default: 45384 return Identifiers.propertyInterpolateV; 45385 } 45386} 45387/** 45388 * Gets the instruction to generate for an interpolated attribute 45389 * @param interpolation An Interpolation AST 45390 */ 45391 45392 45393function getAttributeInterpolationExpression(interpolation) { 45394 switch (getInterpolationArgsLength(interpolation)) { 45395 case 3: 45396 return Identifiers.attributeInterpolate1; 45397 45398 case 5: 45399 return Identifiers.attributeInterpolate2; 45400 45401 case 7: 45402 return Identifiers.attributeInterpolate3; 45403 45404 case 9: 45405 return Identifiers.attributeInterpolate4; 45406 45407 case 11: 45408 return Identifiers.attributeInterpolate5; 45409 45410 case 13: 45411 return Identifiers.attributeInterpolate6; 45412 45413 case 15: 45414 return Identifiers.attributeInterpolate7; 45415 45416 case 17: 45417 return Identifiers.attributeInterpolate8; 45418 45419 default: 45420 return Identifiers.attributeInterpolateV; 45421 } 45422} 45423/** 45424 * Gets the instruction to generate for interpolated text. 45425 * @param interpolation An Interpolation AST 45426 */ 45427 45428 45429function getTextInterpolationExpression(interpolation) { 45430 switch (getInterpolationArgsLength(interpolation)) { 45431 case 1: 45432 return Identifiers.textInterpolate; 45433 45434 case 3: 45435 return Identifiers.textInterpolate1; 45436 45437 case 5: 45438 return Identifiers.textInterpolate2; 45439 45440 case 7: 45441 return Identifiers.textInterpolate3; 45442 45443 case 9: 45444 return Identifiers.textInterpolate4; 45445 45446 case 11: 45447 return Identifiers.textInterpolate5; 45448 45449 case 13: 45450 return Identifiers.textInterpolate6; 45451 45452 case 15: 45453 return Identifiers.textInterpolate7; 45454 45455 case 17: 45456 return Identifiers.textInterpolate8; 45457 45458 default: 45459 return Identifiers.textInterpolateV; 45460 } 45461} 45462/** 45463 * Parse a template into render3 `Node`s and additional metadata, with no other dependencies. 45464 * 45465 * @param template text of the template to parse 45466 * @param templateUrl URL to use for source mapping of the parsed template 45467 * @param options options to modify how the template is parsed 45468 */ 45469 45470 45471function parseTemplate(template, templateUrl, options = {}) { 45472 const { 45473 interpolationConfig,
45474 preserveWhitespaces, 45475 enableI18nLegacyMessageIdFormat 45476 } = options; 45477 const bindingParser = makeBindingParser(interpolationConfig); 45478 const htmlParser = new HtmlParser(); 45479 const parseResult = htmlParser.parse(template, templateUrl, { 45480 leadingTriviaChars: LEADING_TRIVIA_CHARS, 45481 ...options, 45482 tokenizeExpansionForms: true 45483 }); 45484 45485 if (!options.alwaysAttemptHtmlToR3AstConversion && parseResult.errors && parseResult.errors.length > 0) { 45486 const parsedTemplate = { 45487 interpolationConfig, 45488 preserveWhitespaces, 45489 errors: parseResult.errors, 45490 nodes: [], 45491 styleUrls: [], 45492 styles: [], 45493 ngContentSelectors: [] 45494 }; 45495 45496 if (options.collectCommentNodes) { 45497 parsedTemplate.commentNodes = []; 45498 } 45499 45500 return parsedTemplate; 45501 } 45502 45503 let rootNodes = parseResult.rootNodes; // process i18n meta information (scan attributes, generate ids) 45504 // before we run whitespace removal process, because existing i18n 45505 // extraction process (ng extract-i18n) relies on a raw content to generate 45506 // message ids 45507 45508 const i18nMetaVisitor = new I18nMetaVisitor(interpolationConfig, 45509 /* keepI18nAttrs */ 45510 !preserveWhitespaces, enableI18nLegacyMessageIdFormat); 45511 const i18nMetaResult = i18nMetaVisitor.visitAllWithErrors(rootNodes); 45512 45513 if (!options.alwaysAttemptHtmlToR3AstConversion && i18nMetaResult.errors && i18nMetaResult.errors.length > 0) { 45514 const parsedTemplate = { 45515 interpolationConfig, 45516 preserveWhitespaces, 45517 errors: i18nMetaResult.errors, 45518 nodes: [], 45519 styleUrls: [], 45520 styles: [], 45521 ngContentSelectors: [] 45522 }; 45523 45524 if (options.collectCommentNodes) { 45525 parsedTemplate.commentNodes = []; 45526 } 45527 45528 return parsedTemplate; 45529 } 45530 45531 rootNodes = i18nMetaResult.rootNodes; 45532 45533 if (!preserveWhitespaces) { 45534 rootNodes = visitAll(new WhitespaceVisitor(), rootNodes); // run i18n meta visitor again in case whitespaces are removed (because that might affect 45535 // generated i18n message content) and first pass indicated that i18n content is present in a 45536 // template. During this pass i18n IDs generated at the first pass will be preserved, so we can 45537 // mimic existing extraction process (ng extract-i18n) 45538 45539 if (i18nMetaVisitor.hasI18nMeta) { 45540 rootNodes = visitAll(new I18nMetaVisitor(interpolationConfig, 45541 /* keepI18nAttrs */ 45542 false), rootNodes); 45543 } 45544 } 45545 45546 const { 45547 nodes, 45548 errors, 45549 styleUrls, 45550 styles, 45551 ngContentSelectors, 45552 commentNodes 45553 } = htmlAstToRender3Ast(rootNodes, bindingParser, { 45554 collectCommentNodes: !!options.collectCommentNodes 45555 }); 45556 errors.push(...parseResult.errors, ...i18nMetaResult.errors); 45557 const parsedTemplate = { 45558 interpolationConfig, 45559 preserveWhitespaces, 45560 errors: errors.length > 0 ? errors : null, 45561 nodes, 45562 styleUrls, 45563 styles, 45564 ngContentSelectors 45565 }; 45566 45567 if (options.collectCommentNodes) { 45568 parsedTemplate.commentNodes = commentNodes; 45569 } 45570 45571 return parsedTemplate; 45572} 45573 45574const elementRegistry = new DomElementSchemaRegistry(); 45575/** 45576 * Construct a `BindingParser` with a default configuration. 45577 */ 45578 45579function makeBindingParser(interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) { 45580 return new BindingParser(new Parser$1(new Lexer()), interpolationConfig, elementRegistry, []); 45581} 45582 45583function resolveSanitizationFn(context, isAttribute) { 45584 switch (context) { 45585 case SecurityContext.HTML: 45586 return importExpr(Identifiers.sanitizeHtml); 45587 45588 case SecurityContext.SCRIPT: 45589 return importExpr(Identifiers.sanitizeScript); 45590 45591 case SecurityContext.STYLE: 45592 // the compiler does not fill in an instruction for [style.prop?] binding 45593 // values because the style algorithm knows internally what props are subject 45594 // to sanitization (only [attr.style] values are explicitly sanitized) 45595 return isAttribute ? importExpr(Identifiers.sanitizeStyle) : null; 45596 45597 case SecurityContext.URL: 45598 return importExpr(Identifiers.sanitizeUrl); 45599 45600 case SecurityContext.RESOURCE_URL: 45601 return importExpr(Identifiers.sanitizeResourceUrl); 45602 45603 default: 45604 return null; 45605 } 45606} 45607 45608function trustedConstAttribute(tagName, attr) { 45609 const value = asLiteral(attr.value); 45610 45611 if (isTrustedTypesSink(tagName, attr.name)) { 45612 switch (elementRegistry.securityContext(tagName, attr.name, 45613 /* isAttribute */ 45614 true)) { 45615 case SecurityContext.HTML: 45616 return taggedTemplate(importExpr(Identifiers.trustConstantHtml), new TemplateLiteral([new TemplateLiteralElement(attr.value)], []), undefined, attr.valueSpan); 45617 // NB: no SecurityContext.SCRIPT here, as the corresponding tags are stripped by the compiler. 45618 45619 case SecurityContext.RESOURCE_URL: 45620 return taggedTemplate(importExpr(Identifiers.trustConstantResourceUrl), new TemplateLiteral([new TemplateLiteralElement(attr.value)], []), undefined, attr.valueSpan); 45621 45622 default: 45623 return value; 45624 } 45625 } else { 45626 return value; 45627 } 45628} 45629 45630function isSingleElementTemplate(children) { 45631 return children.length === 1 && children[0] instanceof Element$1; 45632} 45633 45634function isTextNode(node) { 45635 return node instanceof Text$3 || node instanceof BoundText || node instanceof Icu$1; 45636} 45637 45638function hasTextChildrenOnly(children) { 45639 return children.every(isTextNode); 45640} 45641 45642function getBindingFunctionParams(deferredParams, name, eagerParams) { 45643 return () => { 45644 const value = deferredParams(); 45645 const fnParams = Array.isArray(value) ? value : [value]; 45646 45647 if (eagerParams) { 45648 fnParams.push(...eagerParams); 45649 } 45650 45651 if (name) { 45652 // We want the property name to always be the first function parameter. 45653 fnParams.unshift(literal(name)); 45654 } 45655 45656 return fnParams; 45657 }; 45658} 45659/** Name of the global variable that is used to determine if we use Closure translations or not */ 45660 45661 45662const NG_I18N_CLOSURE_MODE = 'ngI18nClosureMode'; 45663/** 45664 * Generate statements that define a given translation message. 45665 * 45666 * ``` 45667 * var I18N_1; 45668 * if (typeof ngI18nClosureMode !== undefined && ngI18nClosureMode) { 45669 * var MSG_EXTERNAL_XXX = goog.getMsg( 45670 * "Some message with {$interpolation}!", 45671 * { "interpolation": "\uFFFD0\uFFFD" } 45672 * ); 45673 * I18N_1 = MSG_EXTERNAL_XXX; 45674 * } 45675 * else { 45676 * I18N_1 = $localize`Some message with ${'\uFFFD0\uFFFD'}!`; 45677 * } 45678 * ``` 45679 * 45680 * @param message The original i18n AST message node 45681 * @param variable The variable that will be assigned the translation, e.g. `I18N_1`. 45682 * @param closureVar The variable for Closure `goog.getMsg` calls, e.g. `MSG_EXTERNAL_XXX`. 45683 * @param params Object mapping placeholder names to their values (e.g. 45684 * `{ "interpolation": "\uFFFD0\uFFFD" }`). 45685 * @param transformFn Optional transformation function that will be applied to the translation (e.g. 45686 * post-processing). 45687 * @returns An array of statements that defined a given translation. 45688 */ 45689 45690function getTranslationDeclStmts(message, variable, closureVar, params = {}, transformFn) { 45691 const statements = [declareI18nVariable(variable), ifStmt(createClosureModeGuard(), createGoogleGetMsgStatements(variable, message, closureVar, params), createLocalizeStatements(variable, message, formatI18nPlaceholderNamesInMap(params, 45692 /* useCamelCase */ 45693 false)))]; 45694 45695 if (transformFn) {
45696 statements.push(new ExpressionStatement(variable.set(transformFn(variable)))); 45697 } 45698 45699 return statements; 45700} 45701/** 45702 * Create the expression that will be used to guard the closure mode block 45703 * It is equivalent to: 45704 * 45705 * ``` 45706 * typeof ngI18nClosureMode !== undefined && ngI18nClosureMode 45707 * ``` 45708 */ 45709 45710 45711function createClosureModeGuard() { 45712 return typeofExpr(variable(NG_I18N_CLOSURE_MODE)).notIdentical(literal('undefined', STRING_TYPE)).and(variable(NG_I18N_CLOSURE_MODE)); 45713} 45714 45715function flatten(list) { 45716 return list.reduce((flat, item) => { 45717 const flatItem = Array.isArray(item) ? flatten(item) : item; 45718 return flat.concat(flatItem); 45719 }, []); 45720} 45721/** 45722 * @license 45723 * Copyright Google LLC All Rights Reserved. 45724 * 45725 * Use of this source code is governed by an MIT-style license that can be 45726 * found in the LICENSE file at https://angular.io/license 45727 */ 45728// This regex matches any binding names that contain the "attr." prefix, e.g. "attr.required" 45729// If there is a match, the first matching group will contain the attribute name to bind. 45730 45731 45732const ATTR_REGEX = /attr\.([^\]]+)/;
45733const COMPONENT_VARIABLE = '%COMP%'; 45734const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`; 45735const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`; 45736 45737function baseDirectiveFields(meta, constantPool, bindingParser) { 45738 const definitionMap = new DefinitionMap(); 45739 const selectors = parseSelectorToR3Selector(meta.selector); // e.g. `type: MyDirective` 45740 45741 definitionMap.set('type', meta.internalType); // e.g. `selectors: [['', 'someDir', '']]` 45742 45743 if (selectors.length > 0) { 45744 definitionMap.set('selectors', asLiteral(selectors)); 45745 } 45746 45747 if (meta.queries.length > 0) { 45748 // e.g. `contentQueries: (rf, ctx, dirIndex) => { ... } 45749 definitionMap.set('contentQueries', createContentQueriesFunction(meta.queries, constantPool, meta.name)); 45750 } 45751 45752 if (meta.viewQueries.length) { 45753 definitionMap.set('viewQuery', createViewQueriesFunction(meta.viewQueries, constantPool, meta.name)); 45754 } // e.g. `hostBindings: (rf, ctx) => { ... } 45755 45756 45757 definitionMap.set('hostBindings', createHostBindingsFunction(meta.host, meta.typeSourceSpan, bindingParser, constantPool, meta.selector || '', meta.name, definitionMap)); // e.g 'inputs: {a: 'a'}` 45758 45759 definitionMap.set('inputs', conditionallyCreateMapObjectLiteral(meta.inputs, true)); // e.g 'outputs: {a: 'a'}` 45760 45761 definitionMap.set('outputs', conditionallyCreateMapObjectLiteral(meta.outputs)); 45762 45763 if (meta.exportAs !== null) { 45764 definitionMap.set('exportAs', literalArr(meta.exportAs.map(e => literal(e)))); 45765 } 45766 45767 if (meta.isStandalone) { 45768 definitionMap.set('standalone', literal(true)); 45769 } 45770 45771 return definitionMap; 45772} 45773/** 45774 * Add features to the definition map. 45775 */ 45776 45777 45778function addFeatures(definitionMap, meta) { 45779 // e.g. `features: [NgOnChangesFeature]` 45780 const features = []; 45781 const providers = meta.providers; 45782 const viewProviders = meta.viewProviders; 45783 45784 if (providers || viewProviders) { 45785 const args = [providers || new LiteralArrayExpr([])]; 45786 45787 if (viewProviders) { 45788 args.push(viewProviders); 45789 } 45790 45791 features.push(importExpr(Identifiers.ProvidersFeature).callFn(args)); 45792 } 45793 45794 if (meta.usesInheritance) { 45795 features.push(importExpr(Identifiers.InheritDefinitionFeature)); 45796 } 45797 45798 if (meta.fullInheritance) { 45799 features.push(importExpr(Identifiers.CopyDefinitionFeature)); 45800 } 45801 45802 if (meta.lifecycle.usesOnChanges) { 45803 features.push(importExpr(Identifiers.NgOnChangesFeature)); 45804 } // TODO: better way of differentiating component vs directive metadata. 45805 45806 45807 if (meta.hasOwnProperty('template') && meta.isStandalone) { 45808 features.push(importExpr(Identifiers.StandaloneFeature)); 45809 } 45810 45811 if (features.length) { 45812 definitionMap.set('features', literalArr(features)); 45813 } 45814} 45815/** 45816 * Compile a directive for the render3 runtime as defined by the `R3DirectiveMetadata`. 45817 */ 45818 45819 45820function compileDirectiveFromMetadata(meta, constantPool, bindingParser) { 45821 const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser); 45822 addFeatures(definitionMap, meta); 45823 const expression = importExpr(Identifiers.defineDirective).callFn([definitionMap.toLiteralMap()], undefined, true); 45824 const type = createDirectiveType(meta); 45825 return { 45826 expression, 45827 type, 45828 statements: [] 45829 }; 45830} 45831/** 45832 * Compile a component for the render3 runtime as defined by the `R3ComponentMetadata`. 45833 */ 45834 45835 45836function compileComponentFromMetadata(meta, constantPool, bindingParser) { 45837 const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser); 45838 addFeatures(definitionMap, meta); 45839 const selector = meta.selector && CssSelector.parse(meta.selector); 45840 const firstSelector = selector && selector[0]; // e.g. `attr: ["class", ".my.app"]` 45841 // This is optional an only included if the first selector of a component specifies attributes. 45842 45843 if (firstSelector) { 45844 const selectorAttributes = firstSelector.getAttrs(); 45845 45846 if (selectorAttributes.length) { 45847 definitionMap.set('attrs', constantPool.getConstLiteral(literalArr(selectorAttributes.map(value => value != null ? literal(value) : literal(undefined))), 45848 /* forceShared */ 45849 true)); 45850 } 45851 } // e.g. `template: function MyComponent_Template(_ctx, _cm) {...}` 45852 45853 45854 const templateTypeName = meta.name; 45855 const templateName = templateTypeName ? `${templateTypeName}_Template` : null; 45856 const changeDetection = meta.changeDetection; 45857 const template = meta.template; 45858 const templateBuilder = new TemplateDefinitionBuilder(constantPool, BindingScope.createRootScope(), 0, templateTypeName, null, null, templateName, Identifiers.namespaceHTML, meta.relativeContextFilePath, meta.i18nUseExternalIds); 45859 const templateFunctionExpression = templateBuilder.buildTemplateFunction(template.nodes, []); // We need to provide this so that dynamically generated components know what 45860 // projected content blocks to pass through to the component when it is instantiated. 45861 45862 const ngContentSelectors = templateBuilder.getNgContentSelectors(); 45863 45864 if (ngContentSelectors) { 45865 definitionMap.set('ngContentSelectors', ngContentSelectors); 45866 } // e.g. `decls: 2` 45867 45868 45869 definitionMap.set('decls', literal(templateBuilder.getConstCount())); // e.g. `vars: 2` 45870 45871 definitionMap.set('vars', literal(templateBuilder.getVarCount())); // Generate `consts` section of ComponentDef: 45872 // - either as an array: 45873 // `consts: [['one', 'two'], ['three', 'four']]` 45874 // - or as a factory function in case additional statements are present (to support i18n): 45875 // `consts: function() { var i18n_0; if (ngI18nClosureMode) {...} else {...} return [i18n_0]; }` 45876 45877 const { 45878 constExpressions, 45879 prepareStatements 45880 } = templateBuilder.getConsts(); 45881 45882 if (constExpressions.length > 0) {
45883 let constsExpr = literalArr(constExpressions); // Prepare statements are present - turn `consts` into a function. 45884 45885 if (prepareStatements.length > 0) { 45886 constsExpr = fn([], [...prepareStatements, new ReturnStatement(constsExpr)]); 45887 } 45888 45889 definitionMap.set('consts', constsExpr); 45890 } 45891 45892 definitionMap.set('template', templateFunctionExpression); 45893 45894 if (meta.declarations.length > 0) { 45895 definitionMap.set('dependencies', compileDeclarationList(literalArr(meta.declarations.map(decl => decl.type)), meta.declarationListEmitMode)); 45896 } 45897 45898 if (meta.encapsulation === null) { 45899 meta.encapsulation = ViewEncapsulation.Emulated; 45900 } // e.g. `styles: [str1, str2]` 45901 45902 45903 if (meta.styles && meta.styles.length) { 45904 const styleValues = meta.encapsulation == ViewEncapsulation.Emulated ? compileStyles(meta.styles, CONTENT_ATTR, HOST_ATTR) : meta.styles; 45905 const styleNodes = styleValues.reduce((result, style) => { 45906 if (style.trim().length > 0) { 45907 result.push(constantPool.getConstLiteral(literal(style))); 45908 } 45909 45910 return result; 45911 }, []); 45912 45913 if (styleNodes.length > 0) { 45914 definitionMap.set('styles', literalArr(styleNodes)); 45915 } 45916 } else if (meta.encapsulation === ViewEncapsulation.Emulated) { 45917 // If there is no style, don't generate css selectors on elements 45918 meta.encapsulation = ViewEncapsulation.None; 45919 } // Only set view encapsulation if it's not the default value 45920 45921 45922 if (meta.encapsulation !== ViewEncapsulation.Emulated) { 45923 definitionMap.set('encapsulation', literal(meta.encapsulation)); 45924 } // e.g. `animation: [trigger('123', [])]` 45925 45926 45927 if (meta.animations !== null) { 45928 definitionMap.set('data', literalMap([{ 45929 key: 'animation', 45930 value: meta.animations, 45931 quoted: false 45932 }])); 45933 } // Only set the change detection flag if it's defined and it's not the default. 45934 45935 45936 if (changeDetection != null && changeDetection !== ChangeDetectionStrategy.Default) { 45937 definitionMap.set('changeDetection', literal(changeDetection)); 45938 } 45939 45940 const expression = importExpr(Identifiers.defineComponent).callFn([definitionMap.toLiteralMap()], undefined, true); 45941 const type = createComponentType(meta); 45942 return { 45943 expression, 45944 type, 45945 statements: [] 45946 }; 45947} 45948/** 45949 * Creates the type specification from the component meta. This type is inserted into .d.ts files 45950 * to be consumed by upstream compilations. 45951 */ 45952 45953 45954function createComponentType(meta) { 45955 const typeParams = createBaseDirectiveTypeParams(meta); 45956 typeParams.push(stringArrayAsType(meta.template.ngContentSelectors)); 45957 typeParams.push(expressionType(literal(meta.isStandalone))); 45958 return expressionType(importExpr(Identifiers.ComponentDeclaration, typeParams)); 45959} 45960/** 45961 * Compiles the array literal of declarations into an expression according to the provided emit 45962 * mode. 45963 */ 45964 45965 45966function compileDeclarationList(list, mode) { 45967 switch (mode) { 45968 case 0 45969 /* DeclarationListEmitMode.Direct */ 45970 : 45971 // directives: [MyDir], 45972 return list; 45973 45974 case 1 45975 /* DeclarationListEmitMode.Closure */ 45976 : 45977 // directives: function () { return [MyDir]; }
45978 return fn([], [new ReturnStatement(list)]); 45979 45980 case 2 45981 /* DeclarationListEmitMode.ClosureResolved */ 45982 : 45983 // directives: function () { return [MyDir].map(ng.resolveForwardRef); } 45984 const resolvedList = list.prop('map').callFn([importExpr(Identifiers.resolveForwardRef)]); 45985 return fn([], [new ReturnStatement(resolvedList)]); 45986 } 45987} 45988 45989function prepareQueryParams(query, constantPool) { 45990 const parameters = [getQueryPredicate(query, constantPool), literal(toQueryFlags(query))]; 45991 45992 if (query.read) { 45993 parameters.push(query.read); 45994 } 45995 45996 return parameters; 45997} 45998/** 45999 * Translates query flags into `TQueryFlags` type in packages/core/src/render3/interfaces/query.ts 46000 * @param query 46001 */ 46002 46003 46004function toQueryFlags(query) { 46005 return (query.descendants ? 1 46006 /* QueryFlags.descendants */ 46007 : 0 46008 /* QueryFlags.none */ 46009 ) | (query.static ? 2 46010 /* QueryFlags.isStatic */ 46011 : 0 46012 /* QueryFlags.none */ 46013 ) | (query.emitDistinctChangesOnly ? 4 46014 /* QueryFlags.emitDistinctChangesOnly */ 46015 : 0 46016 /* QueryFlags.none */ 46017 ); 46018} 46019 46020function convertAttributesToExpressions(attributes) { 46021 const values = []; 46022 46023 for (let key of Object.getOwnPropertyNames(attributes)) { 46024 const value = attributes[key]; 46025 values.push(literal(key), value); 46026 } 46027 46028 return values; 46029} // Define and update any content queries 46030 46031 46032function createContentQueriesFunction(queries, constantPool, name) { 46033 const createStatements = []; 46034 const updateStatements = []; 46035 const tempAllocator = temporaryAllocator(updateStatements, TEMPORARY_NAME); 46036 46037 for (const query of queries) { 46038 // creation, e.g. r3.contentQuery(dirIndex, somePredicate, true, null); 46039 createStatements.push(importExpr(Identifiers.contentQuery).callFn([variable('dirIndex'), ...prepareQueryParams(query, constantPool)]).toStmt()); // update, e.g. (r3.queryRefresh(tmp = r3.loadQuery()) && (ctx.someDir = tmp)); 46040 46041 const temporary = tempAllocator(); 46042 const getQueryList = importExpr(Identifiers.loadQuery).callFn([]); 46043 const refresh = importExpr(Identifiers.queryRefresh).callFn([temporary.set(getQueryList)]); 46044 const updateDirective = variable(CONTEXT_NAME).prop(query.propertyName).set(query.first ? temporary.prop('first') : temporary); 46045 updateStatements.push(refresh.and(updateDirective).toStmt()); 46046 } 46047 46048 const contentQueriesFnName = name ? `${name}_ContentQueries` : null; 46049 return fn([new FnParam(RENDER_FLAGS, NUMBER_TYPE), new FnParam(CONTEXT_NAME, null), new FnParam('dirIndex', null)], [renderFlagCheckIfStmt(1 46050 /* core.RenderFlags.Create */ 46051 , createStatements), renderFlagCheckIfStmt(2 46052 /* core.RenderFlags.Update */ 46053 , updateStatements)], INFERRED_TYPE, null, contentQueriesFnName); 46054} 46055 46056function stringAsType(str) { 46057 return expressionType(literal(str)); 46058} 46059 46060function stringMapAsType(map) { 46061 const mapValues = Object.keys(map).map(key => { 46062 const value = Array.isArray(map[key]) ? map[key][0] : map[key]; 46063 return { 46064 key, 46065 value: literal(value), 46066 quoted: true 46067 }; 46068 }); 46069 return expressionType(literalMap(mapValues)); 46070} 46071 46072function stringArrayAsType(arr) { 46073 return arr.length > 0 ? expressionType(literalArr(arr.map(value => literal(value)))) : NONE_TYPE; 46074} 46075 46076function createBaseDirectiveTypeParams(meta) { 46077 // On the type side, remove newlines from the selector as it will need to fit into a TypeScript 46078 // string literal, which must be on one line. 46079 const selectorForType = meta.selector !== null ? meta.selector.replace(/\n/g, '') : null; 46080 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))]; 46081} 46082/** 46083 * Creates the type specification from the directive meta. This type is inserted into .d.ts files 46084 * to be consumed by upstream compilations. 46085 */ 46086 46087 46088function createDirectiveType(meta) { 46089 const typeParams = createBaseDirectiveTypeParams(meta); // Directives have no NgContentSelectors slot, but instead express a `never` type 46090 // so that future fields align. 46091 46092 typeParams.push(NONE_TYPE); 46093 typeParams.push(expressionType(literal(meta.isStandalone))); 46094 return expressionType(importExpr(Identifiers.DirectiveDeclaration, typeParams)); 46095} // Define and update any view queries 46096 46097 46098function createViewQueriesFunction(viewQueries, constantPool, name) { 46099 const createStatements = []; 46100 const updateStatements = []; 46101 const tempAllocator = temporaryAllocator(updateStatements, TEMPORARY_NAME);
46102 viewQueries.forEach(query => { 46103 // creation, e.g. r3.viewQuery(somePredicate, true); 46104 const queryDefinition = importExpr(Identifiers.viewQuery).callFn(prepareQueryParams(query, constantPool)); 46105 createStatements.push(queryDefinition.toStmt()); // update, e.g. (r3.queryRefresh(tmp = r3.loadQuery()) && (ctx.someDir = tmp)); 46106 46107 const temporary = tempAllocator(); 46108 const getQueryList = importExpr(Identifiers.loadQuery).callFn([]); 46109 const refresh = importExpr(Identifiers.queryRefresh).callFn([temporary.set(getQueryList)]); 46110 const updateDirective = variable(CONTEXT_NAME).prop(query.propertyName).set(query.first ? temporary.prop('first') : temporary); 46111 updateStatements.push(refresh.and(updateDirective).toStmt()); 46112 }); 46113 const viewQueryFnName = name ? `${name}_Query` : null; 46114 return fn([new FnParam(RENDER_FLAGS, NUMBER_TYPE), new FnParam(CONTEXT_NAME, null)], [renderFlagCheckIfStmt(1 46115 /* core.RenderFlags.Create */ 46116 , createStatements), renderFlagCheckIfStmt(2 46117 /* core.RenderFlags.Update */ 46118 , updateStatements)], INFERRED_TYPE, null, viewQueryFnName); 46119} // Return a host binding function or null if one is not necessary. 46120 46121 46122function createHostBindingsFunction(hostBindingsMetadata, typeSourceSpan, bindingParser, constantPool, selector, name, definitionMap) { 46123 const bindingContext = variable(CONTEXT_NAME); 46124 const styleBuilder = new StylingBuilder(bindingContext); 46125 const { 46126 styleAttr, 46127 classAttr 46128 } = hostBindingsMetadata.specialAttributes; 46129 46130 if (styleAttr !== undefined) { 46131 styleBuilder.registerStyleAttr(styleAttr); 46132 } 46133 46134 if (classAttr !== undefined) { 46135 styleBuilder.registerClassAttr(classAttr); 46136 } 46137 46138 const createInstructions = []; 46139 const updateInstructions = []; 46140 const updateVariables = []; 46141 const hostBindingSourceSpan = typeSourceSpan; // Calculate host event bindings 46142 46143 const eventBindings = bindingParser.createDirectiveHostEventAsts(hostBindingsMetadata.listeners, hostBindingSourceSpan); 46144 46145 if (eventBindings && eventBindings.length) { 46146 createInstructions.push(...createHostListeners(eventBindings, name)); 46147 } // Calculate the host property bindings 46148 46149 46150 const bindings = bindingParser.createBoundHostProperties(hostBindingsMetadata.properties, hostBindingSourceSpan); 46151 const allOtherBindings = []; // We need to calculate the total amount of binding slots required by 46152 // all the instructions together before any value conversions happen. 46153 // Value conversions may require additional slots for interpolation and 46154 // bindings with pipes. These calculates happen after this block. 46155 46156 let totalHostVarsCount = 0;
46157 bindings && bindings.forEach(binding => { 46158 const stylingInputWasSet = styleBuilder.registerInputBasedOnName(binding.name, binding.expression, hostBindingSourceSpan); 46159 46160 if (stylingInputWasSet) { 46161 totalHostVarsCount += MIN_STYLING_BINDING_SLOTS_REQUIRED; 46162 } else { 46163 allOtherBindings.push(binding); 46164 totalHostVarsCount++; 46165 } 46166 }); 46167 let valueConverter; 46168 46169 const getValueConverter = () => { 46170 if (!valueConverter) { 46171 const hostVarsCountFn = numSlots => { 46172 const originalVarsCount = totalHostVarsCount; 46173 totalHostVarsCount += numSlots; 46174 return originalVarsCount; 46175 }; 46176 46177 valueConverter = new ValueConverter(constantPool, () => error('Unexpected node'), // new nodes are illegal here 46178 hostVarsCountFn, () => error('Unexpected pipe')); // pipes are illegal here 46179 } 46180 46181 return valueConverter; 46182 }; 46183 46184 const propertyBindings = []; 46185 const attributeBindings = []; 46186 const syntheticHostBindings = []; 46187 46188 for (const binding of allOtherBindings) { 46189 // resolve literal arrays and literal objects 46190 const value = binding.expression.visit(getValueConverter()); 46191 const bindingExpr = bindingFn(bindingContext, value); 46192 const { 46193 bindingName, 46194 instruction, 46195 isAttribute 46196 } = getBindingNameAndInstruction(binding); 46197 const securityContexts = bindingParser.calcPossibleSecurityContexts(selector, bindingName, isAttribute).filter(context => context !== SecurityContext.NONE); 46198 let sanitizerFn = null; 46199 46200 if (securityContexts.length) { 46201 if (securityContexts.length === 2 && securityContexts.indexOf(SecurityContext.URL) > -1 && securityContexts.indexOf(SecurityContext.RESOURCE_URL) > -1) { 46202 // Special case for some URL attributes (such as "src" and "href") that may be a part 46203 // of different security contexts. In this case we use special sanitization function and 46204 // select the actual sanitizer at runtime based on a tag name that is provided while 46205 // invoking sanitization function. 46206 sanitizerFn = importExpr(Identifiers.sanitizeUrlOrResourceUrl); 46207 } else { 46208 sanitizerFn = resolveSanitizationFn(securityContexts[0], isAttribute); 46209 } 46210 } 46211 46212 const instructionParams = [literal(bindingName), bindingExpr.currValExpr]; 46213 46214 if (sanitizerFn) { 46215 instructionParams.push(sanitizerFn); 46216 } 46217 46218 updateVariables.push(...bindingExpr.stmts); 46219 46220 if (instruction === Identifiers.hostProperty) { 46221 propertyBindings.push(instructionParams); 46222 } else if (instruction === Identifiers.attribute) { 46223 attributeBindings.push(instructionParams); 46224 } else if (instruction === Identifiers.syntheticHostProperty) { 46225 syntheticHostBindings.push(instructionParams); 46226 } else { 46227 updateInstructions.push({ 46228 reference: instruction, 46229 paramsOrFn: instructionParams, 46230 span: null 46231 }); 46232 } 46233 } 46234 46235 for (const bindingParams of propertyBindings) { 46236 updateInstructions.push({ 46237 reference: Identifiers.hostProperty, 46238 paramsOrFn: bindingParams, 46239 span: null 46240 }); 46241 } 46242 46243 for (const bindingParams of attributeBindings) { 46244 updateInstructions.push({ 46245 reference: Identifiers.attribute, 46246 paramsOrFn: bindingParams, 46247 span: null 46248 }); 46249 } 46250 46251 for (const bindingParams of syntheticHostBindings) { 46252 updateInstructions.push({ 46253 reference: Identifiers.syntheticHostProperty, 46254 paramsOrFn: bindingParams, 46255 span: null 46256 }); 46257 } // since we're dealing with directives/components and both have hostBinding 46258 // functions, we need to generate a special hostAttrs instruction that deals 46259 // with both the assignment of styling as well as static attributes to the host 46260 // element. The instruction below will instruct all initial styling (styling 46261 // that is inside of a host binding within a directive/component) to be attached 46262 // to the host element alongside any of the provided host attributes that were 46263 // collected earlier. 46264 46265 46266 const hostAttrs = convertAttributesToExpressions(hostBindingsMetadata.attributes); 46267 styleBuilder.assignHostAttrs(hostAttrs, definitionMap); 46268 46269 if (styleBuilder.hasBindings) { 46270 // finally each binding that was registered in the statement above will need to be added to 46271 // the update block of a component/directive templateFn/hostBindingsFn so that the bindings 46272 // are evaluated and updated for the element. 46273 styleBuilder.buildUpdateLevelInstructions(getValueConverter()).forEac
46273h(instruction => { 46274 for (const call of instruction.calls) { 46275 // we subtract a value of `1` here because the binding slot was already allocated 46276 // at the top of this method when all the input bindings were counted. 46277 totalHostVarsCount += Math.max(call.allocateBindingSlots - MIN_STYLING_BINDING_SLOTS_REQUIRED, 0); 46278 updateInstructions.push({ 46279 reference: instruction.reference, 46280 paramsOrFn: convertStylingCall(call, bindingContext, bindingFn), 46281 span: null 46282 }); 46283 } 46284 }); 46285 } 46286 46287 if (totalHostVarsCount) { 46288 definitionMap.set('hostVars', literal(totalHostVarsCount)); 46289 } 46290 46291 if (createInstructions.length > 0 || updateInstructions.length > 0) { 46292 const hostBindingsFnName = name ? `${name}_HostBindings` : null; 46293 const statements = []; 46294 46295 if (createInstructions.length > 0) { 46296 statements.push(renderFlagCheckIfStmt(1 46297 /* core.RenderFlags.Create */ 46298 , getInstructionStatements(createInstructions))); 46299 } 46300 46301 if (updateInstructions.length > 0) { 46302 statements.push(renderFlagCheckIfStmt(2 46303 /* core.RenderFlags.Update */ 46304 , updateVariables.concat(getInstructionStatements(updateInstructions)))); 46305 } 46306 46307 return fn([new FnParam(RENDER_FLAGS, NUMBER_TYPE), new FnParam(CONTEXT_NAME, null)], statements, INFERRED_TYPE, null, hostBindingsFnName); 46308 } 46309 46310 return null; 46311} 46312 46313function bindingFn(implicit, value) { 46314 return convertPropertyBinding(null, implicit, value, 'b'); 46315} 46316 46317function convertStylingCall(call, bindingContext, bindingFn) { 46318 return call.params(value => bindingFn(bindingContext, value).currValExpr); 46319} 46320 46321function getBindingNameAndInstruction(binding) { 46322 let bindingName = binding.name; 46323 let instruction; // Check to see if this is an attr binding or a property binding 46324 46325 const attrMatches = bindingName.match(ATTR_REGEX); 46326 46327 if (attrMatches) { 46328 bindingName = attrMatches[1]; 46329 instruction = Identifiers.attribute; 46330 } else { 46331 if (binding.isAnimation) { 46332 bindingName = prepareSyntheticPropertyName(bindingName); // host bindings that have a synthetic property (e.g. @foo) should always be rendered 46333 // in the context of the component and not the parent. Therefore there is a special 46334 // compatibility instruction available for this purpose. 46335 46336 instruction = Identifiers.syntheticHostProperty; 46337 } else { 46338 instruction = Identifiers.hostProperty; 46339 } 46340 } 46341 46342 return { 46343 bindingName, 46344 instruction, 46345 isAttribute: !!attrMatches 46346 }; 46347} 46348 46349function createHostListeners(eventBindings, name) { 46350 const listenerParams = []; 46351 const syntheticListenerParams = []; 46352 const instructions = []; 46353 46354 for (const binding of eventBindings) { 46355 let bindingName = binding.name && sanitizeIdentifier(binding.name); 46356 const bindingFnName = binding.type === 1 46357 /* ParsedEventType.Animation */ 46358 ? prepareSyntheticListenerFunctionName(bindingName, binding.targetOrPhase) : bindingName; 46359 const handlerName = name && bindingName ? `${name}_${bindingFnName}_HostBindingHandler` : null; 46360 const params = prepareEventListenerParameters(BoundEvent.fromParsedEvent(binding), handlerName); 46361 46362 if (binding.type == 1 46363 /* ParsedEventType.Animation */ 46364 ) { 46365 syntheticListenerParams.push(params); 46366 } else { 46367 listenerParams.push(params); 46368 } 46369 } 46370 46371 for (const params of syntheticListenerParams) { 46372 instructions.push({ 46373 reference: Identifiers.syntheticHostListener, 46374 paramsOrFn: params, 46375 span: null 46376 }); 46377 } 46378 46379 for (const params of listenerParams) { 46380 instructions.push({ 46381 reference: Identifiers.listener, 46382 paramsOrFn: params, 46383 span: null 46384 }); 46385 } 46386 46387 return instructions; 46388} 46389 46390const HOST_REG_EXP = /^(?:\[([^\]]+)\])|(?:\(([^\)]+)\))$/; 46391 46392function parseHostBindings(host) { 46393 const attributes = {}; 46394 const listeners = {}; 46395 const properties = {}; 46396 const specialAttributes = {}; 46397 46398 for (const key of Object.keys(host)) { 46399 const value = host[key]; 46400 const matches = key.match(HOST_REG_EXP); 46401 46402 if (matches === null) { 46403 switch (key) { 46404 case 'class': 46405 if (typeof value !== 'string') { 46406 // TODO(alxhub): make this a diagnostic. 46407 throw new Error(`Class binding must be string`); 46408 } 46409 46410 specialAttributes.classAttr = value; 46411 break; 46412 46413 case 'style': 46414 if (typeof value !== 'string') { 46415 // TODO(alxhub): make this a diagnostic. 46416 throw new Error(`Style binding must be string`); 46417 } 46418 46419 specialAttributes.styleAttr = value; 46420 break; 46421 46422 default: 46423 if (typeof value === 'string') { 46424 attributes[key] = literal(value); 46425 } else { 46426 attributes[key] = value; 46427 } 46428 46429 } 46430 } else if (matches[1 46431 /* HostBindingGroup.Binding */ 46432 ] != null) { 46433 if (typeof value !== 'string') { 46434 // TODO(alxhub): make this a diagnostic. 46435 throw new Error(`Property binding must be string`); 46436 } // synthetic properties (the ones that have a `@` as a prefix) 46437 // are still treated the same as regular properties. Therefore 46438 // there is no point in storing them in a separate map. 46439 46440 46441 properties[matches[1 46442 /* HostBindingGroup.Binding */ 46443 ]] = value; 46444 } else if (matches[2 46445 /* HostBindingGroup.Event */ 46446 ] != null) { 46447 if (typeof value !== 'string') { 46448 // TODO(alxhub): make this a diagnostic. 46449 throw new Error(`Event binding must be string`); 46450 } 46451 46452 listeners[matches[2 46453 /* HostBindingGroup.Event */ 46454 ]] = value; 46455 } 46456 } 46457 46458 return { 46459 attributes, 46460 listeners, 46461 properties, 46462 specialAttributes 46463 }; 46464} 46465/** 46466 * Verifies host bindings and returns the list of errors (if any). Empty array indicates that a 46467 * given set of host bindings has no errors. 46468 * 46469 * @param bindings set of host bindings to verify. 46470 * @param sourceSpan source span where host bindings were defined. 46471 * @returns array of errors associated with a given set of host bindings. 46472 */ 46473 46474 46475function verifyHostBindings(bindings, sourceSpan) { 46476 // TODO: abstract out host bindings verification logic and use it instead of 46477 // creating events and properties ASTs to detect errors (FW-996) 46478 const bindingParser = makeBindingParser(); 46479 bindingParser.createDirectiveHostEventAsts(bindings.listeners, sourceSpan); 46480 bindingParser.createBoundHostProperties(bindings.properties, sourceSpan); 46481 return bindingParser.errors; 46482} 46483 46484function compileStyles(styles, selector, hostSelector) { 46485 const shadowCss = new ShadowCss(); 46486 return styles.map(style => { 46487 return shadowCss.shimCssText(style, selector, hostSelector); 46488 }); 46489} 46490/** 46491 * @license 46492 * Copyright Google LLC All Rights Reserved. 46493 * 46494 * Use of this source code is governed by an MIT-style license that can be 46495 * found in the LICENSE file at https://angular.io/license 46496 */ 46497 46498/** 46499 * An interface for retrieving documents by URL that the compiler uses to 46500 * load templates. 46501 * 46502 * This is an abstract class, rather than an interface, so that it can be used 46503 * as injection token. 46504 */ 46505 46506 46507class ResourceLoader {} 46508/** 46509 * @license 46510 * Copyright Google LLC All Rights Reserved. 46511 * 46512 * Use of this source code is governed by an MIT-style license that can be 46513 * found in the LICENSE file at https://angular.io/license 46514 */ 46515 46516 46517class CompilerFacadeImpl {
46518 constructor(jitEvaluator = new JitEvaluator()) { 46519 this.jitEvaluator = jitEvaluator; 46520 this.FactoryTarget = FactoryTarget$1; 46521 this.ResourceLoader = ResourceLoader; 46522 this.elementSchemaRegistry = new DomElementSchemaRegistry(); 46523 } 46524 46525 compilePipe(angularCoreEnv, sourceMapUrl, facade) { 46526 const metadata = { 46527 name: facade.name, 46528 type: wrapReference(facade.type), 46529 internalType: new WrappedNodeExpr(facade.type), 46530 typeArgumentCount: 0, 46531 deps: null, 46532 pipeName: facade.pipeName, 46533 pure: facade.pure, 46534 isStandalone: facade.isStandalone 46535 }; 46536 const res = compilePipeFromMetadata(metadata); 46537 return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []); 46538 } 46539 46540 compilePipeDeclaration(angularCoreEnv, sourceMapUrl, declaration) { 46541 const meta = convertDeclarePipeFacadeToMetadata(declaration); 46542 const res = compilePipeFromMetadata(meta); 46543 return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []); 46544 } 46545 46546 compileInjectable(angularCoreEnv, sourceMapUrl, facade) { 46547 const { 46548 expression, 46549 statements 46550 } = compileInjectable({ 46551 name: facade.name, 46552 type: wrapReference(facade.type), 46553 internalType: new WrappedNodeExpr(facade.type), 46554 typeArgumentCount: facade.typeArgumentCount, 46555 providedIn: computeProvidedIn(facade.providedIn), 46556 useClass: convertToProviderExpression(facade, 'useClass'), 46557 useFactory: wrapExpression(facade, 'useFactory'), 46558 useValue: convertToProviderExpression(facade, 'useValue'), 46559 useExisting: convertToProviderExpression(facade, 'useExisting'), 46560 deps: facade.deps?.map(convertR3DependencyMetadata) 46561 }, 46562 /* resolveForwardRefs */ 46563 true); 46564 return this.jitExpression(expression, angularCoreEnv, sourceMapUrl, statements); 46565 } 46566 46567 compileInjectableDeclaration(angularCoreEnv, sourceMapUrl, facade) { 46568 const { 46569 expression, 46570 statements 46571 } = compileInjectable({ 46572 name: facade.type.name, 46573 type: wrapReference(facade.type), 46574 internalType: new WrappedNodeExpr(facade.type), 46575 typeArgumentCount: 0, 46576 providedIn: computeProvidedIn(facade.providedIn), 46577 useClass: convertToProviderExpression(facade, 'useClass'), 46578 useFactory: wrapExpression(facade, 'useFactory'), 46579 useValue: convertToProviderExpression(facade, 'useValue'), 46580 useExisting: convertToProviderExpression(facade, 'useExisting'), 46581 deps: facade.deps?.map(convertR3DeclareDependencyMetadata) 46582 }, 46583 /* resolveForwardRefs */ 46584 true); 46585 return this.jitExpression(expression, angularCoreEnv, sourceMapUrl, statements); 46586 } 46587 46588 compileInjector(angularCoreEnv, sourceMapUrl, facade) { 46589 const meta = { 46590 name: facade.name, 46591 type: wrapReference(facade.type), 46592 internalType: new WrappedNodeExpr(facade.type), 46593 providers: facade.providers && facade.providers.length > 0 ? new WrappedNodeExpr(facade.providers) : null, 46594 imports: facade.imports.map(i => new WrappedNodeExpr(i)) 46595 }; 46596 const res = compileInjector(meta); 46597 return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []); 46598 } 46599 46600 compileInjectorDeclaration(angularCoreEnv, sourceMapUrl, declaration) { 46601 const meta = convertDeclareInjectorFacadeToMetadata(declaration); 46602 const res = compileInjector(meta); 46603 return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []); 46604 } 46605 46606 compileNgModule(angularCoreEnv, sourceMapUrl, facade) { 46607 const meta = { 46608 type: wrapReference(facade.type), 46609 internalType: new WrappedNodeExpr(facade.type), 46610 adjacentType: new WrappedNodeExpr(facade.type), 46611 bootstrap: facade.bootstrap.map(wrapReference), 46612 declarations: facade.declarations.map(wrapReference), 46613 publicDeclarationTypes: null, 46614 imports: facade.imports.map(wrapReference), 46615 includeImportTypes: true, 46616 exports: facade.exports.map(wrapReference), 46617 selectorScopeMode: R3SelectorScopeMode.Inline, 46618 containsForwardDecls: false, 46619 schemas: facade.schemas ? facade.schemas.map(wrapReference) : null, 46620 id: facade.id ? new WrappedNodeExpr(facade.id) : null 46621 }; 46622 const res = compileNgModule(meta); 46623 return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []); 46624 } 46625 46626 compileNgModuleDeclaration(angularCoreEnv, sourceMapUrl, declaration) { 46627 const expression = compileNgModuleDeclarationExpression(declaration); 46628 return this.jitExpression(expression, angularCoreEnv, sourceMapUrl, []); 46629 } 46630 46631 compileDirective(angularCoreEnv, sourceMapUrl, facade) { 46632 const meta = convertDirectiveFacadeToMetadata(facade); 46633 return this.compileDirectiveFromMeta(angularCoreEnv, sourceMapUrl, meta); 46634 } 46635 46636 compileDirectiveDeclaration(angularCoreEnv, sourceMapUrl, declaration) { 46637 const typeSourceSpan = this.createParseSourceSpan('Directive', declaration.type.name, sourceMapUrl); 46638 const meta = convertDeclareDirectiveFacadeToMetadata(declaration, typeSourceSpan); 46639 return this.compileDirectiveFromMeta(angularCoreEnv, sourceMapUrl, meta); 46640 } 46641 46642 compileDirectiveFromMeta(angularCoreEnv, sourceMapUrl, meta) { 46643 const constantPool = new ConstantPool(); 46644 const bindingParser = makeBindingParser(); 46645 const res = compileDirectiveFromMetadata(meta, constantPool, bindingParser); 46646 return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, constantPool.statements); 46647 } 46648 46649 compileComponent(angularCoreEnv, sourceMapUrl, facade) { 46650 // Parse the template and check for errors. 46651 const { 46652 template, 46653 interpolation 46654 } = parseJitTemplate(facade.template, facade.name, sourceMapUrl, facade.preserveWhitespace
46654s, facade.interpolation); // Compile the component metadata, including template, into an expression. 46655 46656 const meta = { ...facade, 46657 ...convertDirectiveFacadeToMetadata(facade), 46658 selector: facade.selector || this.elementSchemaRegistry.getDefaultComponentElementName(), 46659 template, 46660 declarations: facade.declarations.map(convertDeclarationFacadeToMetadata), 46661 declarationListEmitMode: 0 46662 /* DeclarationListEmitMode.Direct */ 46663 , 46664 styles: [...facade.styles, ...template.styles], 46665 encapsulation: facade.encapsulation, 46666 interpolation, 46667 changeDetection: facade.changeDetection, 46668 animations: facade.animations != null ? new WrappedNodeExpr(facade.animations) : null, 46669 viewProviders: facade.viewProviders != null ? new WrappedNodeExpr(facade.viewProviders) : null, 46670 relativeContextFilePath: '', 46671 i18nUseExternalIds: true 46672 }; 46673 const jitExpressionSourceMap = `ng:///${facade.name}.js`; 46674 return this.compileComponentFromMeta(angularCoreEnv, jitExpressionSourceMap, meta); 46675 } 46676 46677 compileComponentDeclaration(angularCoreEnv, sourceMapUrl, declaration) { 46678 const typeSourceSpan = this.createParseSourceSpan('Component', declaration.type.name, sourceMapUrl); 46679 const meta = convertDeclareComponentFacadeToMetadata(declaration, typeSourceSpan, sourceMapUrl); 46680 return this.compileComponentFromMeta(angularCoreEnv, sourceMapUrl, meta); 46681 } 46682 46683 compileComponentFromMeta(angularCoreEnv, sourceMapUrl, meta) { 46684 const constantPool = new ConstantPool(); 46685 const bindingParser = makeBindingParser(meta.interpolation); 46686 const res = compileComponentFromMetadata(meta, constantPool, bindingParser); 46687 return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, constantPool.statements); 46688 } 46689 46690 compileFactory(angularCoreEnv, sourceMapUrl, meta) { 46691 const factoryRes = compileFactoryFunction({ 46692 name: meta.name, 46693 type: wrapReference(meta.type), 46694 internalType: new WrappedNodeExpr(meta.type), 46695 typeArgumentCount: meta.typeArgumentCount, 46696 deps: convertR3DependencyMetadataArray(meta.deps), 46697 target: meta.target 46698 }); 46699 return this.jitExpression(factoryRes.expression, angularCoreEnv, sourceMapUrl, factoryRes.statements); 46700 } 46701 46702 compileFactoryDeclaration(angularCoreEnv, sourceMapUrl, meta) { 46703 const factoryRes = compileFactoryFunction({ 46704 name: meta.type.name, 46705 type: wrapReference(meta.type), 46706 internalType: new WrappedNodeExpr(meta.type), 46707 typeArgumentCount: 0, 46708 deps: Array.isArray(meta.deps) ? meta.deps.map(convertR3DeclareDependencyMetadata) : meta.deps, 46709 target: meta.target 46710 }); 46711 return this.jitExpression(factoryRes.expression, angularCoreEnv, sourceMapUrl, factoryRes.statements); 46712 } 46713 46714 createParseSourceSpan(kind, typeName, sourceUrl) { 46715 return r3JitTypeSourceSpan(kind, typeName, sourceUrl); 46716 } 46717 /** 46718 * JIT compiles an expression and returns the result of executing that expression. 46719 * 46720 * @param def the definition which will be compiled and executed to get the value to patch 46721 * @param context an object map of @angular/core symbol names to symbols which will be available 46722 * in the context of the compiled expression 46723 * @param sourceUrl a URL to use for the source map of the compiled expression 46724 * @param preStatements a collection of statements that should be evaluated before the expression. 46725 */ 46726 46727 46728 jitExpression(def, context, sourceUrl, preStatements) { 46729 // The ConstantPool may contain Statements which declare variables used in the final expression. 46730 // Therefore, its statements need to precede the actual JIT operation. The final statement is a 46731 // declaration of $def which is set to the expression being compiled. 46732 const statements = [...preStatements, new DeclareVarStmt('$def', def, undefined, StmtModifier.Exported)]; 46733 const res = this.jitEvaluator.evaluateStatements(sourceUrl, statements, new R3JitReflector(context), 46734 /* enableSourceMaps */ 46735 true); 46736 return res['$def']; 46737 } 46738 46739} 46740 46741function convertToR3QueryMetadata(facade) { 46742 return { ...facade, 46743 predicate: convertQueryPredicate(facade.predicate), 46744 read: facade.read ? new WrappedNodeExpr(facade.read) : null, 46745 static: facade.static, 46746 emitDistinctChangesOnly: facade.emitDistinctChangesOnly 46747 }; 46748} 46749 46750function convertQueryDeclarationToMetadata(declaration) { 46751 return { 46752 propertyName: declaration.propertyName, 46753 first: declaration.first ?? false, 46754 predicate: convertQueryPredicate(declaration.predicate), 46755 descendants: declaration.descendants ?? false, 46756 read: declaration.read ? new WrappedNodeExpr(declaration.read) : null, 46757 static: declaration.static ?? false, 46758 emitDistinctChangesOnly: declaration.emitDistinctChangesOnly ?? true 46759 }; 46760} 46761 46762function convertQueryPredicate(predicate) { 46763 return Array.isArray(predicate) ? // The predicate is an array of str
46763ings so pass it through. 46764 predicate : // The predicate is a type - assume that we will need to unwrap any `forwardRef()` calls. 46765 createMayBeForwardRefExpression(new WrappedNodeExpr(predicate), 1 46766 /* ForwardRefHandling.Wrapped */ 46767 ); 46768} 46769 46770function convertDirectiveFacadeToMetadata(facade) { 46771 const inputsFromMetadata = parseInputOutputs(facade.inputs || []); 46772 const outputsFromMetadata = parseInputOutputs(facade.outputs || []); 46773 const propMetadata = facade.propMetadata; 46774 const inputsFromType = {}; 46775 const outputsFromType = {}; 46776 46777 for (const field in propMetadata) { 46778 if (propMetadata.hasOwnProperty(field)) { 46779 propMetadata[field].forEach(ann => { 46780 if (isInput(ann)) { 46781 inputsFromType[field] = ann.bindingPropertyName ? [ann.bindingPropertyName, field] : field; 46782 } else if (isOutput(ann)) { 46783 outputsFromType[field] = ann.bindingPropertyName || field; 46784 } 46785 }); 46786 } 46787 } 46788 46789 return { ...facade, 46790 typeArgumentCount: 0, 46791 typeSourceSpan: facade.typeSourceSpan, 46792 type: wrapReference(facade.type), 46793 internalType: new WrappedNodeExpr(facade.type), 46794 deps: null, 46795 host: extractHostBindings(facade.propMetadata, facade.typeSourceSpan, facade.host), 46796 inputs: { ...inputsFromMetadata, 46797 ...inputsFromType 46798 }, 46799 outputs: { ...outputsFromMetadata, 46800 ...outputsFromType 46801 }, 46802 queries: facade.queries.map(convertToR3QueryMetadata), 46803 providers: facade.providers != null ? new WrappedNodeExpr(facade.providers) : null, 46804 viewQueries: facade.viewQueries.map(convertToR3QueryMetadata), 46805 fullInheritance: false 46806 }; 46807} 46808 46809function convertDeclareDirectiveFacadeToMetadata(declaration, typeSourceSpan) { 46810 return { 46811 name: declaration.type.name, 46812 type: wrapReference(declaration.type), 46813 typeSourceSpan, 46814 internalType: new WrappedNodeExpr(declaration.type), 46815 selector: declaration.selector ?? null, 46816 inputs: declaration.inputs ?? {}, 46817 outputs: declaration.outputs ?? {}, 46818 host: convertHostDeclarationToMetadata(declaration.host), 46819 queries: (declaration.queries ?? []).map(convertQueryDeclarationToMetadata), 46820 viewQueries: (declaration.viewQueries ?? []).map(convertQueryDeclarationToMetadata), 46821 providers: declaration.providers !== undefined ? new WrappedNodeExpr(declaration.providers) : null, 46822 exportAs: declaration.exportAs ?? null, 46823 usesInheritance: declaration.usesInheritance ?? false, 46824 lifecycle: { 46825 usesOnChanges: declaration.usesOnChanges ?? false 46826 }, 46827 deps: null, 46828 typeArgumentCount: 0, 46829 fullInheritance: false, 46830 isStandalone: declaration.isStandalone ?? false 46831 }; 46832} 46833 46834function convertHostDeclarationToMetadata(host = {}) { 46835 return { 46836 attributes: convertOpaqueValuesToExpressions(host.attributes ?? {}), 46837 listeners: host.listeners ?? {}, 46838 properties: host.properties ?? {}, 46839 specialAttributes: { 46840 classAttr: host.classAttribute, 46841 styleAttr: host.styleAttribute 46842 } 46843 }; 46844} 46845 46846function convertOpaqueValuesToExpressions(obj) { 46847 const result = {}; 46848 46849 for (const key of Object.keys(obj)) { 46850 result[key] = new WrappedNodeExpr(obj[key]); 46851 } 46852 46853 return result; 46854} 46855 46856function convertDeclareComponentFacadeToMetadata(decl, typeSourceSpan, sourceMapUrl) { 46857 const { 46858 template, 46859 interpolation 46860 } = parseJitTemplate(decl.template, decl.type.name, sourceMapUrl, decl.preserveWhitespaces ?? false, decl.interpolation); 46861 const declarations = []; 46862 46863 if (decl.dependencies) { 46864 for (const innerDep of decl.dependencies) { 46865 switch (innerDep.kind) { 46866 case 'directive': 46867 case 'component': 46868 declarations.push(convertDirectiveDeclarationToMetadata(innerDep)); 46869 break; 46870 46871 case 'pipe': 46872 declarations.push(convertPipeDeclarationToMetadata(innerDep)); 46873 break; 46874 } 46875 } 46876 } else if (decl.components || decl.directives || decl.pipes) { 46877 // Existing declarations on NPM may not be using the new `dependencies` merged field, and may 46878 // have separate fields for dependencies instead. Unify them for JIT compilation. 46879 decl.components && declarations.push(...decl.components.map(dir => convertDirectiveDeclarationToMetadata(dir, 46880 /* isComponent */ 46881 true))); 46882 decl.directives && declarations.push(...decl.directives.map(dir => convertDirectiveDeclarationToMetadata(dir))); 46883 decl.pipes && declarations.push(...convertPipeMapToMetadata(decl.pipes)); 46884 } 46885 46886 return { ...convertDeclareDirectiveFacadeToMetadata(decl, typeSourceSpan), 46887 template, 46888 styles: decl.styles ?? [], 46889 declarations, 46890 viewProviders: decl.viewProviders !== undefined ? new WrappedNodeExpr(decl.viewProviders) : null, 46891 animations: decl.animations !== undefined ? new WrappedNodeExpr(decl.animations) : null, 46892 changeDetection: decl.changeDetection ?? ChangeDetectionStrategy.Default, 46893 encapsulation: decl.encapsulation ?? ViewEncapsulation.Emulated, 46894 interpolation, 46895 declarationListEmitMode: 2 46896 /* DeclarationListEmitMode.ClosureResolved */ 46897 , 46898 relativeContextFilePath: '', 46899 i18nUseExternalIds: true 46900 }; 46901} 46902 46903function convertDeclarationFacadeToMetadata(declaration) { 46904 return { ...declaration, 46905 type: new WrappedNodeExpr(declaration.type) 46906 }; 46907} 46908 46909function convertDirectiveDeclarationToMetadata(declaration, isComponent = null) { 46910 return { 46911 kind: R3TemplateDependencyKind.Directive, 46912 isComponent: isComponent || declaration.kind === 'component', 46913 selector: declaration.selector, 46914 type: new WrappedNodeExpr(declaration.type), 46915 inputs: declaration.inputs ?? [], 46916 outputs: declaration.outputs ?? [], 46917 exportAs: declaration.exportAs ?? null 46918 }; 46919} 46920 46921function convertPipeMapToMetadata(pipes) { 46922 if (!pipes) { 46923 return []; 46924 } 46925 46926 return Object.keys(pipes).map(name => { 46927 return { 46928 kind: R3TemplateDependencyKind.Pipe, 46929 name, 46930 type: new WrappedNodeExpr(pipes[name]) 46931 }; 46932 }); 46933} 46934 46935function convertPipeDeclarationToMetadata(pipe) { 46936 return { 46937 kind: R3TemplateDependencyKind.Pipe, 46938 name: pipe.name, 46939 type: new WrappedNodeExpr(pipe.type) 46940 }; 46941} 46942 46943function parseJitTemplate(template, typeName, sourceMapUrl, preserveWhitespace
46943s, interpolation) { 46944 const interpolationConfig = interpolation ? InterpolationConfig.fromArray(interpolation) : DEFAULT_INTERPOLATION_CONFIG; // Parse the template and check for errors. 46945 46946 const parsed = parseTemplate(template, sourceMapUrl, { 46947 preserveWhitespaces, 46948 interpolationConfig 46949 }); 46950 46951 if (parsed.errors !== null) { 46952 const errors = parsed.errors.map(err => err.toString()).join(', '); 46953 throw new Error(`Errors during JIT compilation of template for ${typeName}: ${errors}`); 46954 } 46955 46956 return { 46957 template: parsed, 46958 interpolation: interpolationConfig 46959 }; 46960} 46961/** 46962 * Convert the expression, if present to an `R3ProviderExpression`. 46963 * 46964 * In JIT mode we do not want the compiler to wrap the expression in a `forwardRef()` call because, 46965 * if it is referencing a type that has not yet been defined, it will have already been wrapped in 46966 * a `forwardRef()` - either by the application developer or during partial-compilation. Thus we can 46967 * use `ForwardRefHandling.None`. 46968 */ 46969 46970 46971function convertToProviderExpression(obj, property) { 46972 if (obj.hasOwnProperty(property)) { 46973 return createMayBeForwardRefExpression(new WrappedNodeExpr(obj[property]), 0 46974 /* ForwardRefHandling.None */ 46975 ); 46976 } else { 46977 return undefined; 46978 } 46979} 46980 46981function wrapExpression(obj, property) { 46982 if (obj.hasOwnProperty(property)) { 46983 return new WrappedNodeExpr(obj[property]); 46984 } else { 46985 return undefined; 46986 } 46987} 46988 46989function computeProvidedIn(providedIn) { 46990 const expression = typeof providedIn === 'function' ? new WrappedNodeExpr(providedIn) : new LiteralExpr(providedIn ?? null); // See `convertToProviderExpression()` for why this uses `ForwardRefHandling.None`. 46991 46992 return createMayBeForwardRefExpression(expression, 0 46993 /* ForwardRefHandling.None */ 46994 ); 46995} 46996 46997function convertR3DependencyMetadataArray(facades) { 46998 return facades == null ? null : facades.map(convertR3DependencyMetadata); 46999} 47000 47001function convertR3DependencyMetadata(facade) { 47002 const isAttributeDep = facade.attribute != null; // both `null` and `undefined` 47003 47004 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 47005 // `attribute` rather than the `token`. 47006 47007 const token = isAttributeDep ? new WrappedNodeExpr(facade.attribute) : rawToken; 47008 return createR3DependencyMetadata(token, isAttributeDep, facade.host, facade.optional, facade.self, facade.skipSelf); 47009} 47010 47011function convertR3DeclareDependencyMetadata(facade) { 47012 const isAttributeDep = facade.attribute ?? false; 47013 const token = facade.token === null ? null : new WrappedNodeExpr(facade.token); 47014 return createR3DependencyMetadata(token, isAttributeDep, facade.host ?? false, facade.optional ?? false, facade.self ?? false, facade.skipSelf ?? false); 47015} 47016 47017function createR3DependencyMetadata(token, isAttributeDep, host, optional, self, skipSelf) { 47018 // If the dep is an `@Attribute()` the `attributeNameType` ought to be the `unknown` type. 47019 // But types are not available at runtime so we just use a literal `"<unknown>"` string as a dummy 47020 // marker. 47021 const attributeNameType = isAttributeDep ? literal('unknown') : null; 47022 return { 47023 token, 47024 attributeNameType, 47025 host, 47026 optional, 47027 self, 47028 skipSelf 47029 }; 47030} 47031 47032function extractHostBindings(propMetadata, sourceSpan, host) { 47033 // First parse the declarations from the metadata. 47034 const bindings = parseHostBindings(host || {}); // After that check host bindings for errors 47035 47036 const errors = verifyHostBindings(bindings, sourceSpan); 47037 47038 if (errors.length) { 47039 throw new Error(errors.map(error => error.msg).join('\n')); 47040 } // Next, loop over the properties of the object, looking for @HostBinding and @HostListener. 47041 47042 47043 for (const field in propMetadata) { 47044 if (propMetadata.hasOwnProperty(field)) { 47045 propMetadata[field].forEach(ann => { 47046 if (isHostBinding(ann)) { 47047 // Since this is a decorator, we know that the value is a class member. Always access it 47048 // through `this` so that further down the line it can't be confused for a literal value 47049 // (e.g. if there's a property called `true`). 47050 bindings.properties[ann.hostPropertyName || field] = getSafePropertyAccessString('this', field); 47051 } else if (isHostListener(ann)) { 47052 bindings.listeners[ann.eventName || field] = `${field}(${(ann.args || []).join(',')})`; 47053 } 47054 }); 47055 } 47056 } 47057 47058 return bindings; 47059} 47060 47061function isHostBinding(value) { 47062 return value.ngMetadataName === 'HostBinding'; 47063} 47064 47065function isHostListener(value) { 47066 return value.ngMetadataName === 'HostListener'; 47067} 47068 47069function isInput(value) { 47070 return value.ngMetadataName === 'Input'; 47071} 47072 47073function isOutput(value) { 47074 return value.ngMetadataName === 'Output'; 47075} 47076 47077function parseInputOutputs(values) { 47078 return values.reduce((results, value) => { 47079 const [field, property] = value.split(':', 2).map(str => str.trim()); 47080 results[field] = property || field; 47081 return results; 47082 }, {}); 47083} 47084 47085function convertDeclarePipeFacadeToMetadata(declaration) { 47086 return { 47087 name: declaration.type.name, 47088 type: wrapReference(declaration.type), 47089 internalType: new WrappedNodeExpr(declaration.type), 47090 typeArgumentCount: 0, 47091 pipeName: declaration.name, 47092 deps: null, 47093 pure: declaration.pure ?? true, 47094 isStandalone: declaration.isStandalone ?? false 47095 }; 47096} 47097 47098function convertDeclareInjectorFacadeToMetadata(declaration) { 47099 return { 47100 name: declaration.type.name, 47101 type: wrapReference(declaration.type), 47102 internalType: new WrappedNodeExpr(declaration.type), 47103 providers: declaration.providers !== undefined && declaration.providers.length > 0 ? new WrappedNodeExpr(declaration.providers) : null, 47104 imports: declaration.imports !== undefined ? declaration.imports.map(i => new WrappedNodeExpr(i)) : [] 47105 }; 47106} 47107 47108function publishFacade(global) { 47109 const ng = global.ng || (global.ng = {}); 47110 ng.ɵcompilerFacade = new CompilerFacadeImpl(); 47111} 47112/** 47113 * @license 47114 * Copyright Google LLC All Rights Reserved. 47115 * 47116 * Use of this source code is governed by an MIT-style license that can be 47117 * found in the LICENSE file at https://angular.io/license 47118 */ 47119 47120 47121const VERSION = new Version('14.2.10'); 47122/** 47123 * @license 47124 * Copyright Google LLC All Rights Reserved. 47125 * 47126 * Use of this source code is governed by an MIT-style license that can be 47127 * found in the LICENSE file at https://angular.io/license 47128 */ 47129 47130class CompilerConfig { 47131 constructor({ 47132 defaultEncapsulation = ViewEncapsulation.Emulated, 47133 useJit = true, 47134 jitDevMode = false, 47135 missingTranslation = null,
47136 preserveWhitespaces, 47137 strictInjectionParameters 47138 } = {}) { 47139 this.defaultEncapsulation = defaultEncapsulation; 47140 this.useJit = !!useJit; 47141 this.jitDevMode = !!jitDevMode; 47142 this.missingTranslation = missingTranslation; 47143 this.preserveWhitespaces = preserveWhitespacesDefault(noUndefined(preserveWhitespaces)); 47144 this.strictInjectionParameters = strictInjectionParameters === true; 47145 } 47146 47147} 47148 47149function preserveWhitespacesDefault(preserveWhitespacesOption, defaultSetting = false) { 47150 return preserveWhitespacesOption === null ? defaultSetting : preserveWhitespacesOption; 47151} 47152/** 47153 * @license 47154 * Copyright Google LLC All Rights Reserved. 47155 * 47156 * Use of this source code is governed by an MIT-style license that can be 47157 * found in the LICENSE file at https://angular.io/license 47158 */ 47159 47160 47161const _I18N_ATTR = 'i18n'; 47162const _I18N_ATTR_PREFIX = 'i18n-'; 47163const _I18N_COMMENT_PREFIX_REGEXP = /^i18n:?/; 47164const MEANING_SEPARATOR = '|'; 47165const ID_SEPARATOR = '@@'; 47166let i18nCommentsWarned = false; 47167/** 47168 * Extract translatable messages from an html AST 47169 */ 47170 47171function extractMessages(nodes, interpolationConfig, implicitTags, implicitAttrs) { 47172 const visitor = new _Visitor(implicitTags, implicitAttrs); 47173 return visitor.extract(nodes, interpolationConfig); 47174} 47175 47176function mergeTranslations(nodes, translations, interpolationConfig, implicitTags, implicitAttrs) { 47177 const visitor = new _Visitor(implicitTags, implicitAttrs); 47178 return visitor.merge(nodes, translations, interpolationConfig); 47179} 47180 47181class ExtractionResult { 47182 constructor(messages, errors) { 47183 this.messages = messages; 47184 this.errors = errors; 47185 } 47186 47187} 47188 47189var _VisitorMode; 47190 47191(function (_VisitorMode) { 47192 _VisitorMode[_VisitorMode["Extract"] = 0] = "Extract"; 47193 _VisitorMode[_VisitorMode["Merge"] = 1] = "Merge"; 47194})(_VisitorMode || (_VisitorMode = {})); 47195/** 47196 * This Visitor is used: 47197 * 1. to extract all the translatable strings from an html AST (see `extract()`), 47198 * 2. to replace the translatable strings with the actual translations (see `merge()`) 47199 * 47200 * @internal 47201 */ 47202 47203 47204class _Visitor { 47205 constructor(_implicitTags, _implicitAttrs) { 47206 this._implicitTags = _implicitTags; 47207 this._implicitAttrs = _implicitAttrs; 47208 } 47209 /** 47210 * Extracts the messages from the tree 47211 */ 47212 47213 47214 extract(nodes, interpolationConfig) { 47215 this._init(_VisitorMode.Extract, interpolationConfig); 47216 47217 nodes.forEach(node => node.visit(this, null)); 47218 47219 if (this._inI18nBlock) { 47220 this._reportError(nodes[nodes.length - 1], 'Unclosed block'); 47221 } 47222 47223 return new ExtractionResult(this._messages, this._errors); 47224 } 47225 /** 47226 * Returns a tree where all translatable nodes are translated 47227 */ 47228 47229 47230 merge(nodes, translations, interpolationConfig) { 47231 this._init(_VisitorMode.Merge, interpolationConfig); 47232 47233 this._translations = translations; // Construct a single fake root element 47234 47235 const wrapper = new Element('wrapper', [], nodes, undefined, undefined, undefined); 47236 const translatedNode = wrapper.visit(this, null); 47237 47238 if (this._inI18nBlock) { 47239 this._reportError(nodes[nodes.length - 1], 'Unclosed block'); 47240 } 47241 47242 return new ParseTreeResult(translatedNode.children, this._errors); 47243 } 47244 47245 visitExpansionCase(icuCase, context) { 47246 // Parse cases for translatable html attributes 47247 const expression = visitAll(this, icuCase.expression, context); 47248 47249 if (this._mode === _VisitorMode.Merge) { 47250 return new ExpansionCase(icuCase.value, expression, icuCase.sourceSpan, icuCase.valueSourceSpan, icuCase.expSourceSpan); 47251 } 47252 } 47253 47254 visitExpansion(icu, context) { 47255 this._mayBeAddBlockChildren(icu); 47256 47257 const wasInIcu = this._inIcu; 47258 47259 if (!this._inIcu) { 47260 // nested ICU messages should not be extracted but top-level translated as a whole 47261 if (this._isInTranslatableSection) { 47262 this._addMessage([icu]); 47263 } 47264 47265 this._inIcu = true; 47266 } 47267 47268 const cases = visitAll(this, icu.cases, context); 47269 47270 if (this._mode === _VisitorMode.Merge) { 47271 icu = new Expansion(icu.switchValue, icu.type, cases, icu.sourceSpan, icu.switchValueSourceSpan); 47272 } 47273 47274 this._inIcu = wasInIcu; 47275 return icu; 47276 } 47277 47278 visitComment(comment, context) { 47279 const isOpening = _isOpeningComment(comment); 47280 47281 if (isOpening && this._isInTranslatableSection) { 47282 this._reportError(comment, 'Could not start a block inside a translatable section'); 47283 47284 return; 47285 } 47286 47287 const isClosing = _isClosingComment(comment); 47288 47289 if (isClosing && !this._inI18nBlock) { 47290 this._reportError(comment, 'Trying to close an unopened block'); 47291 47292 return; 47293 } 47294 47295 if (!this._inI18nNode && !this._inIcu) { 47296 if (!this._inI18nBlock) { 47297 if (isOpening) { 47298 // deprecated from v5 you should use <ng-container i18n> instead of i18n comments 47299 if (!i18nCommentsWarned && console && console.warn) { 47300 i18nCommentsWarned = true; 47301 const details = comment.sourceSpan.details ? `, ${comment.sourceSpan.details}` : ''; // TODO(ocombe): use a log service once there is a public one available 47302 47303 console.warn(`I18n comments are deprecated, use an <ng-container> element instead (${comment.sourceSpan.start}${details})`); 47304 } 47305 47306 this._inI18nBlock = true; 47307 this._blockStartDepth = this._depth; 47308 this._blockChildren = []; 47309 this._blockMeaningAndDesc = comment.value.replace(_I18N_COMMENT_PREFIX_REGEXP, '').trim(); 47310 47311 this._openTranslatableSection(comment); 47312 } 47313 } else { 47314 if (isClosing) { 47315 if (this._depth == this._blockStartDepth) { 47316 this._closeTranslatableSection(comment, this._blockChildren); 47317 47318 this._inI18nBlock = false;
47319 47320 const message = this._addMessage(this._blockChildren, this._blockMeaningAndDesc); // merge attributes in sections 47321 47322 47323 const nodes = this._translateMessage(comment, message); 47324 47325 return visitAll(this, nodes); 47326 } else { 47327 this._reportError(comment, 'I18N blocks should not cross element boundaries'); 47328 47329 return; 47330 } 47331 } 47332 } 47333 } 47334 } 47335 47336 visitText(text, context) { 47337 if (this._isInTranslatableSection) { 47338 this._mayBeAddBlockChildren(text); 47339 } 47340 47341 return text; 47342 } 47343 47344 visitElement(el, context) { 47345 this._mayBeAddBlockChildren(el); 47346 47347 this._depth++; 47348 const wasInI18nNode = this._inI18nNode; 47349 const wasInImplicitNode = this._inImplicitNode; 47350 let childNodes = []; 47351 let translatedChildNodes = undefined; // Extract: 47352 // - top level nodes with the (implicit) "i18n" attribute if not already in a section 47353 // - ICU messages 47354 47355 const i18nAttr = _getI18nAttr(el); 47356 47357 const i18nMeta = i18nAttr ? i18nAttr.value : ''; 47358 const isImplicit = this._implicitTags.some(tag => el.name === tag) && !this._inIcu && !this._isInTranslatableSection; 47359 const isTopLevelImplicit = !wasInImplicitNode && isImplicit; 47360 this._inImplicitNode = wasInImplicitNode || isImplicit; 47361 47362 if (!this._isInTranslatableSection && !this._inIcu) { 47363 if (i18nAttr || isTopLevelImplicit) { 47364 this._inI18nNode = true; 47365 47366 const message = this._addMessage(el.children, i18nMeta); 47367 47368 translatedChildNodes = this._translateMessage(el, message); 47369 } 47370 47371 if (this._mode == _VisitorMode.Extract) { 47372 const isTranslatable = i18nAttr || isTopLevelImplicit; 47373 if (isTranslatable) this._openTranslatableSection(el); 47374 visitAll(this, el.children); 47375 if (isTranslatable) this._closeTranslatableSection(el, el.children); 47376 } 47377 } else { 47378 if (i18nAttr || isTopLevelImplicit) { 47379 this._reportError(el, 'Could not mark an element as translatable inside a translatable section'); 47380 } 47381 47382 if (this._mode == _VisitorMode.Extract) { 47383 // Descend into child nodes for extraction 47384 visitAll(this, el.children); 47385 } 47386 } 47387 47388 if (this._mode === _VisitorMode.Merge) { 47389 const visitNodes = translatedChildNodes || el.children; 47390 visitNodes.forEach(child => { 47391 const visited = child.visit(this, context); 47392 47393 if (visited && !this._isInTranslatableSection) { 47394 // Do not add the children from translatable sections (= i18n blocks here) 47395 // They will be added later in this loop when the block closes (i.e. on `<!-- /i18n -->`) 47396 childNodes = childNodes.concat(visited); 47397 } 47398 }); 47399 } 47400 47401 this._visitAttributesOf(el); 47402 47403 this._depth--; 47404 this._inI18nNode = wasInI18nNode; 47405 this._inImplicitNode = wasInImplicitNode; 47406 47407 if (this._mode === _VisitorMode.Merge) { 47408 const translatedAttrs = this._translateAttributes(el); 47409 47410 return new Element(el.name, translatedAttrs, childNodes, el.sourceSpan, el.startSourceSpan, el.endSourceSpan); 47411 } 47412 47413 return null; 47414 } 47415 47416 visitAttribute(attribute, context) { 47417 throw new Error('unreachable code'); 47418 } 47419 47420 _init(mode, interpolationConfig) { 47421 this._mode = mode; 47422 this._inI18nBlock = false; 47423 this._inI18nNode = false; 47424 this._depth = 0; 47425 this._inIcu = false; 47426 this._msgCountAtSectionStart = undefined; 47427 this._errors = []; 47428 this._messages = []; 47429 this._inImplicitNode = false; 47430 this._createI18nMessage = createI18nMessageFactory(interpolationConfig); 47431 } // looks for translatable attributes 47432 47433 47434 _visitAttributesOf(el) { 47435 const explicitAttrNameToValue = {}; 47436 const implicitAttrNames = this._implicitAttrs[el.name] || []; 47437 el.attrs.filter(attr => attr.name.startsWith(_I18N_ATTR_PREFIX)).forEach(attr => explicitAttrNameToValue[attr.name.slice(_I18N_ATTR_PREFIX.length)] = attr.value); 47438 el.attrs.forEach(attr => { 47439 if (attr.name in explicitAttrNameToValue) { 47440 this._addMessage([attr], explicitAttrNameToValue[attr.name]); 47441 } else if (implicitAttrNames.some(name => attr.name === name)) { 47442 this._addMessage([attr]); 47443 } 47444 }); 47445 } // add a translatable message 47446 47447 47448 _addMessage(ast, msgMeta) { 47449 if (ast.length == 0 || ast.length == 1 && ast[0] instanceof Attribute && !ast[0].value) {
47450 // Do not create empty messages 47451 return null; 47452 } 47453 47454 const { 47455 meaning, 47456 description, 47457 id 47458 } = _parseMessageMeta(msgMeta); 47459 47460 const message = this._createI18nMessage(ast, meaning, description, id); 47461 47462 this._messages.push(message); 47463 47464 return message; 47465 } // Translates the given message given the `TranslationBundle` 47466 // This is used for translating elements / blocks - see `_translateAttributes` for attributes 47467 // no-op when called in extraction mode (returns []) 47468 47469 47470 _translateMessage(el, message) { 47471 if (message && this._mode === _VisitorMode.Merge) { 47472 const nodes = this._translations.get(message); 47473 47474 if (nodes) { 47475 return nodes; 47476 } 47477 47478 this._reportError(el, `Translation unavailable for message id="${this._translations.digest(message)}"`); 47479 } 47480 47481 return []; 47482 } // translate the attributes of an element and remove i18n specific attributes 47483 47484 47485 _translateAttributes(el) { 47486 const attributes = el.attrs; 47487 const i18nParsedMessageMeta = {}; 47488 attributes.forEach(attr => { 47489 if (attr.name.startsWith(_I18N_ATTR_PREFIX)) { 47490 i18nParsedMessageMeta[attr.name.slice(_I18N_ATTR_PREFIX.length)] = _parseMessageMeta(attr.value); 47491 } 47492 }); 47493 const translatedAttributes = []; 47494 attributes.forEach(attr => { 47495 if (attr.name === _I18N_ATTR || attr.name.startsWith(_I18N_ATTR_PREFIX)) { 47496 // strip i18n specific attributes 47497 return; 47498 } 47499 47500 if (attr.value && attr.value != '' && i18nParsedMessageMeta.hasOwnProperty(attr.name)) { 47501 const { 47502 meaning, 47503 description, 47504 id 47505 } = i18nParsedMessageMeta[attr.name]; 47506 47507 const message = this._createI18nMessage([attr], meaning, description, id); 47508 47509 const nodes = this._translations.get(message); 47510 47511 if (nodes) { 47512 if (nodes.length == 0) { 47513 translatedAttributes.push(new Attribute(attr.name, '', attr.sourceSpan, undefined 47514 /* keySpan */ 47515 , undefined 47516 /* valueSpan */ 47517 , undefined 47518 /* valueTokens */ 47519 , undefined 47520 /* i18n */ 47521 )); 47522 } else if (nodes[0] instanceof Text) { 47523 const value = nodes[0].value; 47524 translatedAttributes.push(new Attribute(attr.name, value, attr.sourceSpan, undefined 47525 /* keySpan */ 47526 , undefined 47527 /* valueSpan */ 47528 , undefined 47529 /* valueTokens */ 47530 , undefined 47531 /* i18n */ 47532 )); 47533 } else { 47534 this._reportError(el, `Unexpected translation for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`); 47535 } 47536 } else { 47537 this._reportError(el, `Translation unavailable for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`); 47538 } 47539 } else { 47540 translatedAttributes.push(attr); 47541 } 47542 }); 47543 return translatedAttributes; 47544 } 47545 /** 47546 * Add the node as a child of the block when: 47547 * - we are in a block, 47548 * - we are not inside a ICU message (those are handled separately), 47549 * - the node is a "direct child" of the block 47550 */ 47551 47552 47553 _mayBeAddBlockChildren(node) { 47554 if (this._inI18nBlock && !this._inIcu && this._depth == this._blockStartDepth) { 47555 this._blockChildren.push(node); 47556 } 47557 } 47558 /** 47559 * Marks the start of a section, see `_closeTranslatableSection` 47560 */ 47561 47562 47563 _openTranslatableSection(node) { 47564 if (this._isInTranslatableSection) { 47565 this._reportError(node, 'Unexpected section start'); 47566 } else { 47567 this._msgCountAtSectionStart = this._messages.length; 47568 } 47569 } 47570 /** 47571 * A translatable section could be: 47572 * - the content of translatable element, 47573 * - nodes between `<!-- i18n -->` and `<!-- /i18n -->` comments 47574 */ 47575 47576 47577 get _isInTranslatableSection() { 47578 return this._msgCountAtSectionStart !== void 0; 47579 } 47580 /** 47581 * Terminates a section. 47582 * 47583 * If a section has only one significant children (comments not significant) then we should not 47584 * keep the message from this children: 47585 * 47586 * `<p i18n="meaning|description">{ICU message}</p>` would produce two messages: 47587 * - one for the <p> content with meaning and description, 47588 * - another one for the ICU message. 47589 * 47590 * In this case the last message is discarded as it contains less information (the AST is 47591 * otherwise identical). 47592 * 47593 * Note that we should still keep messages extracted from attributes inside the section (ie in the 47594 * ICU message here) 47595 */ 47596 47597 47598 _closeTranslatableSection(node, directChildren) { 47599 if (!this._isInTranslatableSection) { 47600 this._reportError(node, 'Unexpected section end'); 47601 47602 return; 47603 } 47604 47605 const startIndex = this._msgCountAtSectionStart; 47606 const significantChildren = directChildren.reduce((count, node) => count + (node instanceof Comment ? 0 : 1), 0); 47607 47608 if (significantChildren == 1) { 47609 for (let i = this._messages.length - 1; i >= startIndex; i--) { 47610 const ast = this._messages[i].nodes; 47611 47612 if (!(ast.length == 1 && ast[0] instanceof Text$2)) { 47613 this._messages.splice(i, 1); 47614 47615 break; 47616 } 47617 } 47618 } 47619 47620 this._msgCountAtSectionStart = undefined; 47621 } 47622 47623 _reportError(node, msg) { 47624 this._errors.push(new I18nError(node.sourceSpan, msg)); 47625 } 47626 47627} 47628 47629function _isOpeningComment(n) { 47630 return !!(n instanceof Comment && n.value && n.value.startsWith('i18n')); 47631} 47632 47633function _isClosingComment(n) { 47634 return !!(n instanceof Comment && n.value && n.value === '/i18n'); 47635} 47636 47637function _getI18nAttr(p) { 47638 return p.attrs.find(attr => attr.name === _I18N_ATTR) || null; 47639} 47640 47641function _parseMessageMeta(i18n) { 47642 if (!i18n) return { 47643 meaning: '', 47644 description: '', 47645 id: '' 47646 }; 47647 const idIndex = i18n.indexOf(ID_SEPARATOR); 47648 const descIndex = i18n.indexOf(MEANING_SEPARATOR); 47649 const [meaningAndDesc, id] = idIndex > -1 ? [i18n.slice(0, idIndex), i18n.slice(idIndex + 2)] : [i18n, '']; 47650 const [meaning, description] = descIndex > -1 ? [meaningAndDesc.slice(0, descIndex), meaningAndDesc.slice(descIndex + 1)] : ['', meaningAndDesc]; 47651 return { 47652 meaning, 47653 description, 47654 id: id.trim() 47655 }; 47656} 47657/** 47658 * @license 47659 * Copyright Google LLC All Rights Reserved. 47660 * 47661 * Use of this source code is governed by an MIT-style license that can be 47662 * found in the LICENSE file at https://angular.io/license 47663 */ 47664 47665 47666class XmlTagDefinition { 47667 constructor() { 47668 this.closedByParent = false;
47669 this.isVoid = false; 47670 this.ignoreFirstLf = false; 47671 this.canSelfClose = true; 47672 this.preventNamespaceInheritance = false; 47673 } 47674 47675 requireExtraParent(currentParent) { 47676 return false; 47677 } 47678 47679 isClosedByChild(name) { 47680 return false; 47681 } 47682 47683 getContentType() { 47684 return TagContentType.PARSABLE_DATA; 47685 } 47686 47687} 47688 47689const _TAG_DEFINITION = new XmlTagDefinition(); 47690 47691function getXmlTagDefinition(tagName) { 47692 return _TAG_DEFINITION; 47693} 47694/** 47695 * @license 47696 * Copyright Google LLC All Rights Reserved. 47697 * 47698 * Use of this source code is governed by an MIT-style license that can be 47699 * found in the LICENSE file at https://angular.io/license 47700 */ 47701 47702 47703class XmlParser extends Parser { 47704 constructor() { 47705 super(getXmlTagDefinition); 47706 } 47707 47708 parse(source, url, options) { 47709 return super.parse(source, url, options); 47710 } 47711 47712} 47713/** 47714 * @license 47715 * Copyright Google LLC All Rights Reserved. 47716 * 47717 * Use of this source code is governed by an MIT-style license that can be 47718 * found in the LICENSE file at https://angular.io/license 47719 */ 47720 47721 47722const _VERSION$1 = '1.2'; 47723const _XMLNS$1 = 'urn:oasis:names:tc:xliff:document:1.2'; // TODO(vicb): make this a param (s/_/-/) 47724 47725const _DEFAULT_SOURCE_LANG$1 = 'en'; 47726const _PLACEHOLDER_TAG$2 = 'x'; 47727const _MARKER_TAG$1 = 'mrk'; 47728const _FILE_TAG = 'file'; 47729const _SOURCE_TAG$1 = 'source'; 47730const _SEGMENT_SOURCE_TAG = 'seg-source'; 47731const _ALT_TRANS_TAG = 'alt-trans'; 47732const _TARGET_TAG$1 = 'target'; 47733const _UNIT_TAG$1 = 'trans-unit'; 47734const _CONTEXT_GROUP_TAG = 'context-group'; 47735const _CONTEXT_TAG = 'context'; // https://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html 47736// https://docs.oasis-open.org/xliff/v1.2/xliff-profile-html/xliff-profile-html-1.2.html 47737 47738class Xliff extends Serializer { 47739 write(messages, locale) { 47740 const visitor = new _WriteVisitor$1(); 47741 const transUnits = []; 47742 messages.forEach(message => { 47743 let contextTags = []; 47744 message.sources.forEach(source => { 47745 let contextGroupTag = new Tag(_CONTEXT_GROUP_TAG, { 47746 purpose: 'location' 47747 }); 47748 contextGroupTag.children.push(new CR(10), new Tag(_CONTEXT_TAG, { 47749 'context-type': 'sourcefile' 47750 }, [new Text$1(source.filePath)]), new CR(10), new Tag(_CONTEXT_TAG, { 47751 'context-type': 'linenumber' 47752 }, [new Text$1(`${source.startLine}`)]), new CR(8)); 47753 contextTags.push(new CR(8), contextGroupTag); 47754 }); 47755 const transUnit = new Tag(_UNIT_TAG$1, { 47756 id: message.id, 47757 datatype: 'html' 47758 }); 47759 transUnit.children.push(new CR(8), new Tag(_SOURCE_TAG$1, {}, visitor.serialize(message.nodes)), ...contextTags); 47760 47761 if (message.description) { 47762 transUnit.children.push(new CR(8), new Tag('note', { 47763 priority: '1', 47764 from: 'description' 47765 }, [new Text$1(message.description)])); 47766 } 47767 47768 if (message.meaning) { 47769 transUnit.children.push(new CR(8), new Tag('note', { 47770 priority: '1', 47771 from: 'meaning' 47772 }, [new Text$1(message.meaning)])); 47773 } 47774 47775 transUnit.children.push(new CR(6)); 47776 transUnits.push(new CR(6), transUnit); 47777 }); 47778 const body = new Tag('body', {}, [...transUnits, new CR(4)]); 47779 const file = new Tag('file', { 47780 'source-language': locale || _DEFAULT_SOURCE_LANG$1, 47781 datatype: 'plaintext', 47782 original: 'ng2.template' 47783 }, [new CR(4), body, new CR(2)]); 47784 const xliff = new Tag('xliff', { 47785 version: _VERSION$1, 47786 xmlns: _XMLNS$1 47787 }, [new CR(2), file, new CR()]); 47788 return serialize([new Declaration({ 47789 version: '1.0', 47790 encoding: 'UTF-8' 47791 }), new CR(), xliff, new CR()]); 47792 } 47793 47794 load(content, url) { 47795 // xliff to xml nodes 47796 const xliffParser = new XliffParser(); 47797 const { 47798 locale, 47799 msgIdToHtml, 47800 errors 47801 } = xliffParser.parse(content, url); // xml nodes to i18n nodes 47802 47803 const i18nNodesByMsgId = {}; 47804 const converter = new XmlToI18n$2();
47805 Object.keys(msgIdToHtml).forEach(msgId => { 47806 const { 47807 i18nNodes, 47808 errors: e 47809 } = converter.convert(msgIdToHtml[msgId], url); 47810 errors.push(...e); 47811 i18nNodesByMsgId[msgId] = i18nNodes; 47812 }); 47813 47814 if (errors.length) { 47815 throw new Error(`xliff parse errors:\n${errors.join('\n')}`); 47816 } 47817 47818 return { 47819 locale: locale, 47820 i18nNodesByMsgId 47821 }; 47822 } 47823 47824 digest(message) { 47825 return digest$1(message); 47826 } 47827 47828} 47829 47830class _WriteVisitor$1 { 47831 visitText(text, context) { 47832 return [new Text$1(text.value)]; 47833 } 47834 47835 visitContainer(container, context) { 47836 const nodes = []; 47837 container.children.forEach(node => nodes.push(...node.visit(this))); 47838 return nodes; 47839 } 47840 47841 visitIcu(icu, context) { 47842 const nodes = [new Text$1(`{${icu.expressionPlaceholder}, ${icu.type}, `)]; 47843 Object.keys(icu.cases).forEach(c => { 47844 nodes.push(new Text$1(`${c} {`), ...icu.cases[c].visit(this), new Text$1(`} `)); 47845 }); 47846 nodes.push(new Text$1(`}`)); 47847 return nodes; 47848 } 47849 47850 visitTagPlaceholder(ph, context) { 47851 const ctype = getCtypeForTag(ph.tag); 47852 47853 if (ph.isVoid) { 47854 // void tags have no children nor closing tags 47855 return [new Tag(_PLACEHOLDER_TAG$2, { 47856 id: ph.startName, 47857 ctype, 47858 'equiv-text': `<${ph.tag}/>` 47859 })]; 47860 } 47861 47862 const startTagPh = new Tag(_PLACEHOLDER_TAG$2, { 47863 id: ph.startName, 47864 ctype, 47865 'equiv-text': `<${ph.tag}>` 47866 }); 47867 const closeTagPh = new Tag(_PLACEHOLDER_TAG$2, { 47868 id: ph.closeName, 47869 ctype, 47870 'equiv-text': `</${ph.tag}>` 47871 }); 47872 return [startTagPh, ...this.serialize(ph.children), closeTagPh]; 47873 } 47874 47875 visitPlaceholder(ph, context) { 47876 return [new Tag(_PLACEHOLDER_TAG$2, { 47877 id: ph.name, 47878 'equiv-text': `{{${ph.value}}}` 47879 })]; 47880 } 47881 47882 visitIcuPlaceholder(ph, context) { 47883 const equivText = `{${ph.value.expression}, ${ph.value.type}, ${Object.keys(ph.value.cases).map(value => value + ' {...}').join(' ')}}`; 47884 return [new Tag(_PLACEHOLDER_TAG$2, { 47885 id: ph.name, 47886 'equiv-text': equivText 47887 })]; 47888 } 47889 47890 serialize(nodes) { 47891 return [].concat(...nodes.map(node => node.visit(this))); 47892 } 47893 47894} // TODO(vicb): add error management (structure) 47895// Extract messages as xml nodes from the xliff file 47896 47897 47898class XliffParser { 47899 constructor() { 47900 this._locale = null; 47901 } 47902 47903 parse(xliff, url) { 47904 this._unitMlString = null; 47905 this._msgIdToHtml = {}; 47906 const xml = new XmlParser().parse(xliff, url); 47907 this._errors = xml.errors; 47908 visitAll(this, xml.rootNodes, null); 47909 return { 47910 msgIdToHtml: this._msgIdToHtml, 47911 errors: this._errors, 47912 locale: this._locale 47913 }; 47914 } 47915 47916 visitElement(element, context) { 47917 switch (element.name) { 47918 case _UNIT_TAG$1: 47919 this._unitMlString = null; 47920 const idAttr = element.attrs.find(attr => attr.name === 'id'); 47921 47922 if (!idAttr) { 47923 this._addError(element, `<${_UNIT_TAG$1}> misses the "id" attribute`); 47924 } else { 47925 const id = idAttr.value; 47926 47927 if (this._msgIdToHtml.hasOwnProperty(id)) { 47928 this._addError(element, `Duplicated translations for msg ${id}`); 47929 } else { 47930 visitAll(this, element.children, null); 47931 47932 if (typeof this._unitMlString === 'string') { 47933 this._msgIdToHtml[id] = this._unitMlString; 47934 } else { 47935 this._addError(element, `Message ${id} misses a translation`); 47936 } 47937 } 47938 } 47939 47940 break; 47941 // ignore those tags 47942 47943 case _SOURCE_TAG$1: 47944 case _SEGMENT_SOURCE_TAG: 47945 case _ALT_TRANS_TAG: 47946 break; 47947 47948 case _TARGET_TAG$1: 47949 const innerTextStart = element.startSourceSpan.end.offset; 47950 const innerTextEnd = element.endSourceSpan.start.offset; 47951 const content = element.startSourceSpan.start.file.content; 47952 const innerText = content.slice(innerTextStart, innerTextEnd); 47953 this._unitMlString = innerText; 47954 break; 47955 47956 case _FILE_TAG: 47957 const localeAttr = element.attrs.find(attr => attr.name === 'target-language'); 47958 47959 if (localeAttr) { 47960 this._locale = localeAttr.value; 47961 } 47962 47963 visitAll(this, element.children, null); 47964 break; 47965 47966 default: 47967 // TODO(vicb): assert file structure, xliff version 47968 // For now only recurse on unhandled nodes 47969 visitAll(this, element.children, null); 47970 } 47971 } 47972 47973 visitAttribute(attribute, context) {} 47974 47975 visitText(text, context) {} 47976 47977 visitComment(comment, context) {} 47978 47979 visitExpansion(expansion, context) {} 47980 47981 visitExpansionCase(expansionCase, context) {} 47982 47983 _addError(node, message) { 47984 this._errors.push(new I18nError(node.sourceSpan, message)); 47985 } 47986 47987} // Convert ml nodes (xliff syntax) to i18n nodes 47988 47989 47990class XmlToI18n$2 { 47991 convert(message, url) { 47992 const xmlIcu = new XmlParser().parse(message, url, { 47993 tokenizeExpansionForms: true 47994 }); 47995 this._errors = xmlIcu.errors; 47996 const i18nNodes = this._errors.length > 0 || xmlIcu.rootNodes.length == 0 ? [] : [].concat(...visitAll(this, xmlIcu.rootNodes)); 47997 return { 47998 i18nNodes: i18nNodes, 47999 errors: this._errors 48000 }; 48001 } 48002 48003 visitText(text, context) { 48004 return new Text$2(text.value, text.sourceSpan); 48005 } 48006 48007 visitElement(el, context) { 48008 if (el.name === _PLACEHOLDER_TAG$2) { 48009 const nameAttr = el.attrs.find(attr => attr.name === 'id'); 48010 48011 if (nameAttr) { 48012 return new Placeholder('', nameAttr.value, el.sourceSpan); 48013 } 48014 48015 this._addError(el, `<${_PLACEHOLDER_TAG$2}> misses the "id" attribute`); 48016 48017 return null; 48018 } 48019 48020 if (el.name === _MARKER_TAG$1) { 48021 return [].concat(...visitAll(this, el.children)); 48022 } 48023 48024 this._addError(el, `Unexpected tag`); 48025 48026 return null; 48027 } 48028 48029 visitExpansion(icu, context) { 48030 const caseMap = {};
48031 visitAll(this, icu.cases).forEach(c => { 48032 caseMap[c.value] = new Container(c.nodes, icu.sourceSpan); 48033 }); 48034 return new Icu(icu.switchValue, icu.type, caseMap, icu.sourceSpan); 48035 } 48036 48037 visitExpansionCase(icuCase, context) { 48038 return { 48039 value: icuCase.value, 48040 nodes: visitAll(this, icuCase.expression) 48041 }; 48042 } 48043 48044 visitComment(comment, context) {} 48045 48046 visitAttribute(attribute, context) {} 48047 48048 _addError(node, message) { 48049 this._errors.push(new I18nError(node.sourceSpan, message)); 48050 } 48051 48052} 48053 48054function getCtypeForTag(tag) { 48055 switch (tag.toLowerCase()) { 48056 case 'br': 48057 return 'lb'; 48058 48059 case 'img': 48060 return 'image'; 48061 48062 default: 48063 return `x-${tag}`; 48064 } 48065} 48066/** 48067 * @license 48068 * Copyright Google LLC All Rights Reserved. 48069 * 48070 * Use of this source code is governed by an MIT-style license that can be 48071 * found in the LICENSE file at https://angular.io/license 48072 */ 48073 48074 48075const _VERSION = '2.0'; 48076const _XMLNS = 'urn:oasis:names:tc:xliff:document:2.0'; // TODO(vicb): make this a param (s/_/-/) 48077 48078const _DEFAULT_SOURCE_LANG = 'en'; 48079const _PLACEHOLDER_TAG$1 = 'ph'; 48080const _PLACEHOLDER_SPANNING_TAG = 'pc'; 48081const _MARKER_TAG = 'mrk'; 48082const _XLIFF_TAG = 'xliff'; 48083const _SOURCE_TAG = 'source'; 48084const _TARGET_TAG = 'target'; 48085const _UNIT_TAG = 'unit'; // https://docs.oasis-open.org/xliff/xliff-core/v2.0/os/xliff-core-v2.0-os.html 48086 48087class Xliff2 extends Serializer { 48088 write(messages, locale) { 48089 const visitor = new _WriteVisitor(); 48090 const units = []; 48091 messages.forEach(message => { 48092 const unit = new Tag(_UNIT_TAG, { 48093 id: message.id 48094 }); 48095 const notes = new Tag('notes'); 48096 48097 if (message.description || message.meaning) { 48098 if (message.description) { 48099 notes.children.push(new CR(8), new Tag('note', { 48100 category: 'description' 48101 }, [new Text$1(message.description)])); 48102 } 48103 48104 if (message.meaning) { 48105 notes.children.push(new CR(8), new Tag('note', { 48106 category: 'meaning' 48107 }, [new Text$1(message.meaning)])); 48108 } 48109 } 48110 48111 message.sources.forEach(source => { 48112 notes.children.push(new CR(8), new Tag('note', { 48113 category: 'location' 48114 }, [new Text$1(`${source.filePath}:${source.startLine}${source.endLine !== source.startLine ? ',' + source.endLine : ''}`)])); 48115 }); 48116 notes.children.push(new CR(6)); 48117 unit.children.push(new CR(6), notes); 48118 const segment = new Tag('segment'); 48119 segment.children.push(new CR(8), new Tag(_SOURCE_TAG, {}, visitor.serialize(message.nodes)), new CR(6)); 48120 unit.children.push(new CR(6), segment, new CR(4)); 48121 units.push(new CR(4), unit); 48122 }); 48123 const file = new Tag('file', { 48124 'original': 'ng.template', 48125 id: 'ngi18n' 48126 }, [...units, new CR(2)]); 48127 const xliff = new Tag(_XLIFF_TAG, { 48128 version: _VERSION, 48129 xmlns: _XMLNS, 48130 srcLang: locale || _DEFAULT_SOURCE_LANG 48131 }, [new CR(2), file, new CR()]); 48132 return serialize([new Declaration({ 48133 version: '1.0', 48134 encoding: 'UTF-8' 48135 }), new CR(), xliff, new CR()]); 48136 } 48137 48138 load(content, url) { 48139 // xliff to xml nodes 48140 const xliff2Parser = new Xliff2Parser(); 48141 const { 48142 locale, 48143 msgIdToHtml, 48144 errors 48145 } = xliff2Parser.parse(content, url); // xml nodes to i18n nodes 48146 48147 const i18nNodesByMsgId = {}; 48148 const converter = new XmlToI18n$1(); 48149 Object.keys(msgIdToHtml).forEach(msgId => { 48150 const { 48151 i18nNodes, 48152 errors: e 48153 } = converter.convert(msgIdToHtml[msgId], url); 48154 errors.push(...e); 48155 i18nNodesByMsgId[msgId] = i18nNodes; 48156 }); 48157 48158 if (errors.length) { 48159 throw new Error(`xliff2 parse errors:\n${errors.join('\n')}`); 48160 } 48161 48162 return { 48163 locale: locale, 48164 i18nNodesByMsgId 48165 }; 48166 } 48167 48168 digest(message) { 48169 return decimalDigest(message); 48170 } 48171 48172} 48173 48174class _WriteVisitor { 48175 visitText(text, context) { 48176 return [new Text$1(text.value)]; 48177 } 48178 48179 visitContainer(container, context) { 48180 const nodes = []; 48181 container.children.forEach(node => nodes.push(...node.visit(this))); 48182 return nodes; 48183 } 48184 48185 visitIcu(icu, context) { 48186 const nodes = [new Text$1(`{${icu.expressionPlaceholder}, ${icu.type}, `)];
48187 Object.keys(icu.cases).forEach(c => { 48188 nodes.push(new Text$1(`${c} {`), ...icu.cases[c].visit(this), new Text$1(`} `)); 48189 }); 48190 nodes.push(new Text$1(`}`)); 48191 return nodes; 48192 } 48193 48194 visitTagPlaceholder(ph, context) { 48195 const type = getTypeForTag(ph.tag); 48196 48197 if (ph.isVoid) { 48198 const tagPh = new Tag(_PLACEHOLDER_TAG$1, { 48199 id: (this._nextPlaceholderId++).toString(), 48200 equiv: ph.startName, 48201 type: type, 48202 disp: `<${ph.tag}/>` 48203 }); 48204 return [tagPh]; 48205 } 48206 48207 const tagPc = new Tag(_PLACEHOLDER_SPANNING_TAG, { 48208 id: (this._nextPlaceholderId++).toString(), 48209 equivStart: ph.startName, 48210 equivEnd: ph.closeName, 48211 type: type, 48212 dispStart: `<${ph.tag}>`, 48213 dispEnd: `</${ph.tag}>` 48214 }); 48215 const nodes = [].concat(...ph.children.map(node => node.visit(this))); 48216 48217 if (nodes.length) { 48218 nodes.forEach(node => tagPc.children.push(node)); 48219 } else { 48220 tagPc.children.push(new Text$1('')); 48221 } 48222 48223 return [tagPc]; 48224 } 48225 48226 visitPlaceholder(ph, context) { 48227 const idStr = (this._nextPlaceholderId++).toString(); 48228 return [new Tag(_PLACEHOLDER_TAG$1, { 48229 id: idStr, 48230 equiv: ph.name, 48231 disp: `{{${ph.value}}}` 48232 })]; 48233 } 48234 48235 visitIcuPlaceholder(ph, context) { 48236 const cases = Object.keys(ph.value.cases).map(value => value + ' {...}').join(' '); 48237 const idStr = (this._nextPlaceholderId++).toString(); 48238 return [new Tag(_PLACEHOLDER_TAG$1, { 48239 id: idStr, 48240 equiv: ph.name, 48241 disp: `{${ph.value.expression}, ${ph.value.type}, ${cases}}` 48242 })]; 48243 } 48244 48245 serialize(nodes) { 48246 this._nextPlaceholderId = 0; 48247 return [].concat(...nodes.map(node => node.visit(this))); 48248 } 48249 48250} // Extract messages as xml nodes from the xliff file 48251 48252 48253class Xliff2Parser { 48254 constructor() { 48255 this._locale = null; 48256 } 48257 48258 parse(xliff, url) { 48259 this._unitMlString = null; 48260 this._msgIdToHtml = {}; 48261 const xml = new XmlParser().parse(xliff, url); 48262 this._errors = xml.errors; 48263 visitAll(this, xml.rootNodes, null); 48264 return { 48265 msgIdToHtml: this._msgIdToHtml, 48266 errors: this._errors, 48267 locale: this._locale 48268 }; 48269 } 48270 48271 visitElement(element, context) { 48272 switch (element.name) { 48273 case _UNIT_TAG: 48274 this._unitMlString = null; 48275 const idAttr = element.attrs.find(attr => attr.name === 'id'); 48276 48277 if (!idAttr) { 48278 this._addError(element, `<${_UNIT_TAG}> misses the "id" attribute`); 48279 } else { 48280 const id = idAttr.value; 48281 48282 if (this._msgIdToHtml.hasOwnProperty(id)) { 48283 this._addError(element, `Duplicated translations for msg ${id}`); 48284 } else { 48285 visitAll(this, element.children, null); 48286 48287 if (typeof this._unitMlString === 'string') { 48288 this._msgIdToHtml[id] = this._unitMlString; 48289 } else { 48290 this._addError(element, `Message ${id} misses a translation`); 48291 } 48292 } 48293 } 48294 48295 break; 48296 48297 case _SOURCE_TAG: 48298 // ignore source message 48299 break; 48300 48301 case _TARGET_TAG: 48302 const innerTextStart = element.startSourceSpan.end.offset; 48303 const innerTextEnd = element.endSourceSpan.start.offset; 48304 const content = element.startSourceSpan.start.file.content; 48305 const innerText = content.slice(innerTextStart, innerTextEnd); 48306 this._unitMlString = innerText; 48307 break; 48308 48309 case _XLIFF_TAG: 48310 const localeAttr = element.attrs.find(attr => attr.name === 'trgLang'); 48311 48312 if (localeAttr) { 48313 this._locale = localeAttr.value; 48314 } 48315 48316 const versionAttr = element.attrs.find(attr => attr.name === 'version'); 48317 48318 if (versionAttr) { 48319 const version = versionAttr.value; 48320 48321 if (version !== '2.0') { 48322 this._addError(element, `The XLIFF file version ${version} is not compatible with XLIFF 2.0 serializer`); 48323 } else { 48324 visitAll(this, element.children, null); 48325 } 48326 } 48327 48328 break; 48329 48330 default: 48331 visitAll(this, element.children, null); 48332 } 48333 } 48334 48335 visitAttribute(attribute, context) {} 48336 48337 visitText(text, context) {} 48338 48339 visitComment(comment, context) {} 48340 48341 visitExpansion(expansion, context) {} 48342 48343 visitExpansionCase(expansionCase, context) {} 48344 48345 _addError(node, message) { 48346 this._errors.push(new I18nError(node.sourceSpan, message)); 48347 } 48348 48349} // Convert ml nodes (xliff syntax) to i18n nodes 48350 48351 48352class XmlToI18n$1 { 48353 convert(message, url) { 48354 const xmlIcu = new XmlParser().parse(message, url, { 48355 tokenizeExpansionForms: true 48356 }); 48357 this._errors = xmlIcu.errors; 48358 const i18nNodes = this._errors.length > 0 || xmlIcu.rootNodes.length == 0 ? [] : [].concat(...visitAll(this, xmlIcu.rootNodes)); 48359 return { 48360 i18nNodes, 48361 errors: this._errors 48362 }; 48363 } 48364 48365 visitText(text, context) { 48366 return new Text$2(text.value, text.sourceSpan); 48367 } 48368 48369 visitElement(el, context) { 48370 switch (el.name) { 48371 case _PLACEHOLDER_TAG$1: 48372 const nameAttr = el.attrs.find(attr => attr.name === 'equiv'); 48373 48374 if (nameAttr) { 48375 return [new Placeholder('', nameAttr.value, el.sourceSpan)]; 48376 } 48377 48378 this._addError(el, `<${_PLACEHOLDER_TAG$1}> misses the "equiv" attribute`); 48379 48380 break; 48381 48382 case _PLACEHOLDER_SPANNING_TAG: 48383 const startAttr = el.attrs.find(attr => attr.name === 'equivStart'); 48384 const endAttr = el.attrs.find(attr => attr.name === 'equivEnd'); 48385 48386 if (!startAttr) { 48387 this._addError(el, `<${_PLACEHOLDER_TAG$1}> misses the "equivStart" attribute`); 48388 } else if (!endAttr) { 48389 this._addError(el, `<${_PLACEHOLDER_TAG$1}> misses the "equivEnd" attribute`); 48390 } else { 48391 const startId = startAttr.value; 48392 const endId = endAttr.value; 48393 const nodes = []; 48394 return nodes.concat(new Placeholder('', startId, el.sourceSpan), ...el.children.map(node =>
48394 node.visit(this, null)), new Placeholder('', endId, el.sourceSpan)); 48395 } 48396 48397 break; 48398 48399 case _MARKER_TAG: 48400 return [].concat(...visitAll(this, el.children)); 48401 48402 default: 48403 this._addError(el, `Unexpected tag`); 48404 48405 } 48406 48407 return null; 48408 } 48409 48410 visitExpansion(icu, context) { 48411 const caseMap = {}; 48412 visitAll(this, icu.cases).forEach(c => { 48413 caseMap[c.value] = new Container(c.nodes, icu.sourceSpan); 48414 }); 48415 return new Icu(icu.switchValue, icu.type, caseMap, icu.sourceSpan); 48416 } 48417 48418 visitExpansionCase(icuCase, context) { 48419 return { 48420 value: icuCase.value, 48421 nodes: [].concat(...visitAll(this, icuCase.expression)) 48422 }; 48423 } 48424 48425 visitComment(comment, context) {} 48426 48427 visitAttribute(attribute, context) {} 48428 48429 _addError(node, message) { 48430 this._errors.push(new I18nError(node.sourceSpan, message)); 48431 } 48432 48433} 48434 48435function getTypeForTag(tag) { 48436 switch (tag.toLowerCase()) { 48437 case 'br': 48438 case 'b': 48439 case 'i': 48440 case 'u': 48441 return 'fmt'; 48442 48443 case 'img': 48444 return 'image'; 48445 48446 case 'a': 48447 return 'link'; 48448 48449 default: 48450 return 'other'; 48451 } 48452} 48453/** 48454 * @license 48455 * Copyright Google LLC All Rights Reserved. 48456 * 48457 * Use of this source code is governed by an MIT-style license that can be 48458 * found in the LICENSE file at https://angular.io/license 48459 */ 48460 48461 48462const _TRANSLATIONS_TAG = 'translationbundle'; 48463const _TRANSLATION_TAG = 'translation'; 48464const _PLACEHOLDER_TAG = 'ph'; 48465 48466class Xtb extends Serializer { 48467 write(messages, locale) { 48468 throw new Error('Unsupported'); 48469 } 48470 48471 load(content, url) { 48472 // xtb to xml nodes 48473 const xtbParser = new XtbParser(); 48474 const { 48475 locale, 48476 msgIdToHtml, 48477 errors 48478 } = xtbParser.parse(content, url); // xml nodes to i18n nodes 48479 48480 const i18nNodesByMsgId = {}; 48481 const converter = new XmlToI18n(); // Because we should be able to load xtb files that rely on features not supported by angular, 48482 // we need to delay the conversion of html to i18n nodes so that non angular messages are not 48483 // converted 48484 48485 Object.keys(msgIdToHtml).forEach(msgId => { 48486 const valueFn = function () { 48487 const { 48488 i18nNodes, 48489 errors 48490 } = converter.convert(msgIdToHtml[msgId], url); 48491 48492 if (errors.length) { 48493 throw new Error(`xtb parse errors:\n${errors.join('\n')}`); 48494 } 48495 48496 return i18nNodes; 48497 }; 48498 48499 createLazyProperty(i18nNodesByMsgId, msgId, valueFn); 48500 }); 48501 48502 if (errors.length) { 48503 throw new Error(`xtb parse errors:\n${errors.join('\n')}`); 48504 } 48505 48506 return { 48507 locale: locale, 48508 i18nNodesByMsgId 48509 }; 48510 } 48511 48512 digest(message) { 48513 return digest(message); 48514 } 48515 48516 createNameMapper(message) { 48517 return new SimplePlaceholderMapper(message, toPublicName); 48518 } 48519 48520} 48521 48522function createLazyProperty(messages, id, valueFn) { 48523 Object.defineProperty(messages, id, { 48524 configurable: true, 48525 enumerable: true, 48526 get: function () { 48527 const value = valueFn(); 48528 Object.defineProperty(messages, id, { 48529 enumerable: true, 48530 value 48531 }); 48532 return value; 48533 }, 48534 set: _ => { 48535 throw new Error('Could not overwrite an XTB translation'); 48536 } 48537 }); 48538} // Extract messages as xml nodes from the xtb file 48539 48540 48541class XtbParser { 48542 constructor() { 48543 this._locale = null; 48544 } 48545 48546 parse(xtb, url) { 48547 this._bundleDepth = 0; 48548 this._msgIdToHtml = {}; // We can not parse the ICU messages at this point as some messages might not originate 48549 // from Angular that could not be lex'd. 48550 48551 const xml = new XmlParser().parse(xtb, url); 48552 this._errors = xml.errors; 48553 visitAll(this, xml.rootNodes); 48554 return { 48555 msgIdToHtml: this._msgIdToHtml, 48556 errors: this._errors, 48557 locale: this._locale 48558 }; 48559 } 48560 48561 visitElement(element, context) { 48562 switch (element.name) { 48563 case _TRANSLATIONS_TAG: 48564 this._bundleDepth++; 48565 48566 if (this._bundleDepth > 1) { 48567 this._addError(element, `<${_TRANSLATIONS_TAG}> elements can not be nested`); 48568 } 48569 48570 const langAttr = element.attrs.find(attr => attr.name === 'lang'); 48571 48572 if (langAttr) { 48573 this._locale = langAttr.value; 48574 } 48575 48576 visitAll(this, element.children, null); 48577 this._bundleDepth--; 48578 break; 48579 48580 case _TRANSLATION_TAG: 48581 const idAttr = element.attrs.find(attr => attr.name === 'id'); 48582 48583 if (!idAttr) { 48584 this._addError(element, `<${_TRANSLATION_TAG}> misses the "id" attribute`); 48585 } else { 48586 const id = idAttr.value; 48587 48588 if (this._msgIdToHtml.hasOwnProperty(id)) { 48589 this._addError(element, `Duplicated translations for msg ${id}`); 48590 } else { 48591 const innerTextStart = element.startSourceSpan.end.offset; 48592 const innerTextEnd = element.endSourceSpan.start.offset; 48593 const content = element.startSourceSpan.start.file.content; 48594 const innerText = content.slice(innerTextStart, innerTextEnd); 48595 this._msgIdToHtml[id] = innerText; 48596 } 48597 } 48598 48599 break; 48600 48601 default: 48602 this._addError(element, 'Unexpected tag'); 48603 48604 } 48605 } 48606 48607 visitAttribute(attribute, context) {} 48608 48609 visitText(text, context) {} 48610 48611 visitComment(comment, context) {} 48612 48613 visitExpansion(expansion, context) {} 48614 48615 visitExpansionCase(expansionCase, context) {} 48616 48617 _addError(node, message) { 48618 this._errors.push(new I18nError(node.sourceSpan, message)); 48619 } 48620 48621} // Convert ml nodes (xtb syntax) to i18n nodes 48622 48623 48624class XmlToI18n { 48625 convert(message, url) { 48626 const xmlIcu = new XmlParser().parse(message, url, { 48627 tokenizeExpansionForms: true 48628 }); 48629 this._errors = xmlIcu.errors; 48630 const i18nNodes = this._errors.length > 0 || xmlIcu.rootNodes.length == 0 ? [] : visitAll(this, xmlIcu.rootNodes); 48631 return { 48632 i18nNodes, 48633 errors: this._errors 48634 }; 48635 } 48636 48637 visitText(text, context) { 48638 return new Text$2(text.value, text.sourceSpan); 48639 } 48640 48641 visitExpansion(icu, context) { 48642 const caseMap = {};
48643 visitAll(this, icu.cases).forEach(c => { 48644 caseMap[c.value] = new Container(c.nodes, icu.sourceSpan); 48645 }); 48646 return new Icu(icu.switchValue, icu.type, caseMap, icu.sourceSpan); 48647 } 48648 48649 visitExpansionCase(icuCase, context) { 48650 return { 48651 value: icuCase.value, 48652 nodes: visitAll(this, icuCase.expression) 48653 }; 48654 } 48655 48656 visitElement(el, context) { 48657 if (el.name === _PLACEHOLDER_TAG) { 48658 const nameAttr = el.attrs.find(attr => attr.name === 'name'); 48659 48660 if (nameAttr) { 48661 return new Placeholder('', nameAttr.value, el.sourceSpan); 48662 } 48663 48664 this._addError(el, `<${_PLACEHOLDER_TAG}> misses the "name" attribute`); 48665 } else { 48666 this._addError(el, `Unexpected tag`); 48667 } 48668 48669 return null; 48670 } 48671 48672 visitComment(comment, context) {} 48673 48674 visitAttribute(attribute, context) {} 48675 48676 _addError(node, message) { 48677 this._errors.push(new I18nError(node.sourceSpan, message)); 48678 } 48679 48680} 48681/** 48682 * @license 48683 * Copyright Google LLC All Rights Reserved. 48684 * 48685 * Use of this source code is governed by an MIT-style license that can be 48686 * found in the LICENSE file at https://angular.io/license 48687 */ 48688 48689/** 48690 * A container for translated messages 48691 */ 48692 48693 48694class TranslationBundle { 48695 constructor(_i18nNodesByMsgId = {}, locale, digest, mapperFactory, missingTranslationStrategy = MissingTranslationStrategy.Warning, console) { 48696 this._i18nNodesByMsgId = _i18nNodesByMsgId; 48697 this.digest = digest; 48698 this.mapperFactory = mapperFactory; 48699 this._i18nToHtml = new I18nToHtmlVisitor(_i18nNodesByMsgId, locale, digest, mapperFactory, missingTranslationStrategy, console); 48700 } // Creates a `TranslationBundle` by parsing the given `content` with the `serializer`. 48701 48702 48703 static load(content, url, serializer, missingTranslationStrategy, console) { 48704 const { 48705 locale, 48706 i18nNodesByMsgId 48707 } = serializer.load(content, url); 48708 48709 const digestFn = m => serializer.digest(m); 48710 48711 const mapperFactory = m => serializer.createNameMapper(m); 48712 48713 return new TranslationBundle(i18nNodesByMsgId, locale, digestFn, mapperFactory, missingTranslationStrategy, console); 48714 } // Returns the translation as HTML nodes from the given source message. 48715 48716 48717 get(srcMsg) { 48718 const html = this._i18nToHtml.convert(srcMsg); 48719 48720 if (html.errors.length) { 48721 throw new Error(html.errors.join('\n')); 48722 } 48723 48724 return html.nodes; 48725 } 48726 48727 has(srcMsg) { 48728 return this.digest(srcMsg) in this._i18nNodesByMsgId; 48729 } 48730 48731} 48732 48733class I18nToHtmlVisitor { 48734 constructor(_i18nNodesByMsgId = {}, _locale, _digest, _mapperFactory, _missingTranslationStrategy, _console) { 48735 this._i18nNodesByMsgId = _i18nNodesByMsgId; 48736 this._locale = _locale; 48737 this._digest = _digest; 48738 this._mapperFactory = _mapperFactory; 48739 this._missingTranslationStrategy = _missingTranslationStrategy; 48740 this._console = _console; 48741 this._contextStack = []; 48742 this._errors = []; 48743 } 48744 48745 convert(srcMsg) { 48746 this._contextStack.length = 0; 48747 this._errors.length = 0; // i18n to text 48748 48749 const text = this._convertToText(srcMsg); // text to html 48750 48751 48752 const url = srcMsg.nodes[0].sourceSpan.start.file.url; 48753 const html = new HtmlParser().parse(text, url, { 48754 tokenizeExpansionForms: true 48755 }); 48756 return { 48757 nodes: html.rootNodes, 48758 errors: [...this._errors, ...html.errors] 48759 }; 48760 } 48761 48762 visitText(text, context) { 48763 // `convert()` uses an `HtmlParser` to return `html.Node`s 48764 // we should then make sure that any special characters are escaped 48765 return escapeXml(text.value); 48766 } 48767 48768 visitContainer(container, context) { 48769 return container.children.map(n => n.visit(this)).join(''); 48770 } 48771 48772 visitIcu(icu, context) { 48773 const cases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`); // TODO(vicb): Once all format switch to using expression placeholders 48774 // we should throw when the placeholder is not in the source message 48775 48776 const exp = this._srcMsg.placeholders.hasOwnProperty(icu.expression) ? this._srcMsg.placeholders[icu.expression].text : icu.expression; 48777 return `{${exp}, ${icu.type}, ${cases.join(' ')}}`; 48778 } 48779 48780 visitPlaceholder(ph, context) { 48781 const phName = this._mapper(ph.name); 48782 48783 if (this._srcMsg.placeholders.hasOwnProperty(phName)) { 48784 return this._srcMsg.placeholders[phName].text; 48785 } 48786 48787 if (this._srcMsg.placeholderToMessage.hasOwnProperty(phName)) { 48788 return this._convertToText(this._srcMsg.placeholderToMessage[phName]); 48789 } 48790 48791 this._addError(ph, `Unknown placeholder "${ph.name}"`); 48792 48793 return ''; 48794 } // Loaded message contains only placeholders (vs tag and icu placeholders). 48795 // However when a translation can not be found, we need to serialize the source message 48796 // which can contain tag placeholders 48797 48798 48799 visitTagPlaceholder(ph, context) { 48800 const tag = `${ph.tag}`; 48801 const attrs = Object.keys(ph.attrs).map(name => `${name}="${ph.attrs[name]}"`).join(' '); 48802 48803 if (ph.isVoid) { 48804 return `<${tag} ${attrs}/>`; 48805 } 48806 48807 const children = ph.children.map(c => c.visit(this)).join(''); 48808 return `<${tag} ${attrs}>${children}</${tag}>`; 48809 } // Loaded message contains only placeholders (vs tag and icu placeholders). 48810 // However when a translation can not be found, we need to serialize the source message 48811 // which can contain tag placeholders 48812 48813 48814 visitIcuPlaceholder(ph, context) { 48815 // An ICU placeholder references the source message to be serialized 48816 return this._convertToText(this._srcMsg.placeholderToMessage[ph.name]); 48817 } 48818 /**
48819 * Convert a source message to a translated text string: 48820 * - text nodes are replaced with their translation, 48821 * - placeholders are replaced with their content, 48822 * - ICU nodes are converted to ICU expressions. 48823 */ 48824 48825 48826 _convertToText(srcMsg) { 48827 const id = this._digest(srcMsg); 48828 48829 const mapper = this._mapperFactory ? this._mapperFactory(srcMsg) : null; 48830 let nodes; 48831 48832 this._contextStack.push({ 48833 msg: this._srcMsg, 48834 mapper: this._mapper 48835 }); 48836 48837 this._srcMsg = srcMsg; 48838 48839 if (this._i18nNodesByMsgId.hasOwnProperty(id)) { 48840 // When there is a translation use its nodes as the source 48841 // And create a mapper to convert serialized placeholder names to internal names 48842 nodes = this._i18nNodesByMsgId[id]; 48843 48844 this._mapper = name => mapper ? mapper.toInternalName(name) : name; 48845 } else { 48846 // When no translation has been found 48847 // - report an error / a warning / nothing, 48848 // - use the nodes from the original message 48849 // - placeholders are already internal and need no mapper 48850 if (this._missingTranslationStrategy === MissingTranslationStrategy.Error) { 48851 const ctx = this._locale ? ` for locale "${this._locale}"` : ''; 48852 48853 this._addError(srcMsg.nodes[0], `Missing translation for message "${id}"${ctx}`); 48854 } else if (this._console && this._missingTranslationStrategy === MissingTranslationStrategy.Warning) { 48855 const ctx = this._locale ? ` for locale "${this._locale}"` : ''; 48856 48857 this._console.warn(`Missing translation for message "${id}"${ctx}`); 48858 } 48859 48860 nodes = srcMsg.nodes; 48861 48862 this._mapper = name => name; 48863 } 48864 48865 const text = nodes.map(node => node.visit(this)).join(''); 48866 48867 const context = this._contextStack.pop(); 48868 48869 this._srcMsg = context.msg; 48870 this._mapper = context.mapper; 48871 return text; 48872 } 48873 48874 _addError(el, msg) { 48875 this._errors.push(new I18nError(el.sourceSpan, msg)); 48876 } 48877 48878} 48879/** 48880 * @license 48881 * Copyright Google LLC All Rights Reserved. 48882 * 48883 * Use of this source code is governed by an MIT-style license that can be 48884 * found in the LICENSE file at https://angular.io/license 48885 */ 48886 48887 48888class I18NHtmlParser { 48889 constructor(_htmlParser, translations, translationsFormat, missingTranslation = MissingTranslationStrategy.Warning, console) { 48890 this._htmlParser = _htmlParser; 48891 48892 if (translations) { 48893 const serializer = createSerializer(translationsFormat); 48894 this._translationBundle = TranslationBundle.load(translations, 'i18n', serializer, missingTranslation, console); 48895 } else { 48896 this._translationBundle = new TranslationBundle({}, null, digest$1, undefined, missingTranslation, console); 48897 } 48898 } 48899 48900 parse(source, url, options = {}) { 48901 const interpolationConfig = options.interpolationConfig || DEFAULT_INTERPOLATION_CONFIG; 48902 48903 const parseResult = this._htmlParser.parse(source, url, { 48904 interpolationConfig, 48905 ...options 48906 }); 48907 48908 if (parseResult.errors.length) { 48909 return new ParseTreeResult(parseResult.rootNodes, parseResult.errors); 48910 } 48911 48912 return mergeTranslations(parseResult.rootNodes, this._translationBundle, interpolationConfig, [], {}); 48913 } 48914 48915} 48916 48917function createSerializer(format) { 48918 format = (format || 'xlf').toLowerCase(); 48919 48920 switch (format) { 48921 case 'xmb': 48922 return new Xmb(); 48923 48924 case 'xtb': 48925 return new Xtb(); 48926 48927 case 'xliff2': 48928 case 'xlf2': 48929 return new Xliff2(); 48930 48931 case 'xliff': 48932 case 'xlf': 48933 default: 48934 return new Xliff(); 48935 } 48936} 48937/** 48938 * @license 48939 * Copyright Google LLC All Rights Reserved. 48940 * 48941 * Use of this source code is governed by an MIT-style license that can be 48942 * found in the LICENSE file at https://angular.io/license 48943 */ 48944 48945/** 48946 * A container for message extracted from the templates. 48947 */ 48948 48949 48950class MessageBundle { 48951 constructor(_htmlParser, _implicitTags, _implicitAttrs, _locale = null) { 48952 this._htmlParser = _htmlParser; 48953 this._implicitTags = _implicitTags; 48954 this._implicitAttrs = _implicitAttrs; 48955 this._locale = _locale; 48956 this._messages = []; 48957 } 48958 48959 updateFromTemplate(html, url, interpolationConfig) { 48960 const htmlParserResult = this._htmlParser.parse(html, url, { 48961 tokenizeExpansionForms: true, 48962 interpolationConfig 48963 }); 48964 48965 if (htmlParserResult.errors.length) { 48966 return htmlParserResult.errors; 48967 } 48968 48969 const i18nParserResult = extractMessages(htmlParserResult.rootNodes, interpolationConfig, this._implicitTags, this._implicitAttrs); 48970 48971 if (i18nParserResult.errors.length) { 48972 return i18nParserResult.errors; 48973 } 48974 48975 this._messages.push(...i18nParserResult.messages); 48976 48977 return []; 48978 } // Return the message in the internal format 48979 // The public (serialized) format might be different, see the `write` method. 48980 48981 48982 getMessages() { 48983 return this._messages; 48984 } 48985
48986 write(serializer, filterSources) { 48987 const messages = {}; 48988 const mapperVisitor = new MapPlaceholderNames(); // Deduplicate messages based on their ID 48989 48990 this._messages.forEach(message => { 48991 const id = serializer.digest(message); 48992 48993 if (!messages.hasOwnProperty(id)) { 48994 messages[id] = message; 48995 } else { 48996 messages[id].sources.push(...message.sources); 48997 } 48998 }); // Transform placeholder names using the serializer mapping 48999 49000 49001 const msgList = Object.keys(messages).map(id => { 49002 const mapper = serializer.createNameMapper(messages[id]); 49003 const src = messages[id]; 49004 const nodes = mapper ? mapperVisitor.convert(src.nodes, mapper) : src.nodes; 49005 let transformedMessage = new Message(nodes, {}, {}, src.meaning, src.description, id); 49006 transformedMessage.sources = src.sources; 49007 49008 if (filterSources) { 49009 transformedMessage.sources.forEach(source => source.filePath = filterSources(source.filePath)); 49010 } 49011 49012 return transformedMessage; 49013 }); 49014 return serializer.write(msgList, this._locale); 49015 } 49016 49017} // Transform an i18n AST by renaming the placeholder nodes with the given mapper 49018 49019 49020class MapPlaceholderNames extends CloneVisitor { 49021 convert(nodes, mapper) { 49022 return mapper ? nodes.map(n => n.visit(this, mapper)) : nodes; 49023 } 49024 49025 visitTagPlaceholder(ph, mapper) { 49026 const startName = mapper.toPublicName(ph.startName); 49027 const closeName = ph.closeName ? mapper.toPublicName(ph.closeName) : ph.closeName; 49028 const children = ph.children.map(n => n.visit(this, mapper)); 49029 return new TagPlaceholder(ph.tag, ph.attrs, startName, closeName, children, ph.isVoid, ph.sourceSpan, ph.startSourceSpan, ph.endSourceSpan); 49030 } 49031 49032 visitPlaceholder(ph, mapper) { 49033 return new Placeholder(ph.value, mapper.toPublicName(ph.name), ph.sourceSpan); 49034 } 49035 49036 visitIcuPlaceholder(ph, mapper) { 49037 return new IcuPlaceholder(ph.value, mapper.toPublicName(ph.name), ph.sourceSpan); 49038 } 49039 49040} 49041/** 49042 * @license 49043 * Copyright Google LLC All Rights Reserved. 49044 * 49045 * Use of this source code is governed by an MIT-style license that can be 49046 * found in the LICENSE file at https://angular.io/license 49047 */ 49048 49049 49050var FactoryTarget; 49051 49052(function (FactoryTarget) { 49053 FactoryTarget[FactoryTarget["Directive"] = 0] = "Directive"; 49054 FactoryTarget[FactoryTarget["Component"] = 1] = "Component"; 49055 FactoryTarget[FactoryTarget["Injectable"] = 2] = "Injectable"; 49056 FactoryTarget[FactoryTarget["Pipe"] = 3] = "Pipe"; 49057 FactoryTarget[FactoryTarget["NgModule"] = 4] = "NgModule"; 49058})(FactoryTarget || (FactoryTarget = {})); 49059/** 49060 * @license 49061 * Copyright Google LLC All Rights Reserved. 49062 * 49063 * Use of this source code is governed by an MIT-style license that can be 49064 * found in the LICENSE file at https://angular.io/license 49065 */ 49066 49067/** 49068 * @license 49069 * Copyright Google LLC All Rights Reserved. 49070 * 49071 * Use of this source code is governed by an MIT-style license that can be 49072 * found in the LICENSE file at https://angular.io/license 49073 */ 49074 49075/** 49076 * Processes `Target`s with a given set of directives and performs a binding operation, which 49077 * returns an object similar to TypeScript's `ts.TypeChecker` that contains knowledge about the 49078 * target. 49079 */ 49080 49081 49082class R3TargetBinder { 49083 constructor(directiveMatcher) { 49084 this.directiveMatcher = directiveMatcher; 49085 } 49086 /** 49087 * Perform a binding operation on the given `Target` and return a `BoundTarget` which contains 49088 * metadata about the types referenced in the template. 49089 */ 49090 49091 49092 bind(target) { 49093 if (!target.template) { 49094 // TODO(alxhub): handle targets which contain things like HostBindings, etc. 49095 throw new Error('Binding without a template not yet supported'); 49096 } // First, parse the template into a `Scope` structure. This operation captures the syntactic 49097 // scopes in the template and makes them available for later use. 49098 49099 49100 const scope = Scope.apply(target.template); // Use the `Scope` to extract the entities present at every level of the template. 49101 49102 const templateEntities = extractTemplateEntities(scope); // Next, perform directive matching on the template using the `DirectiveBinder`. This returns: 49103 // - directives: Map of nodes (elements & ng-templates) to the directives on them. 49104 // - bindings: Map of inputs, outputs, and attributes to the directive/element that claims 49105 // them. TODO(alxhub): handle multiple directives claiming an input/output/etc. 49106 // - references: Map of #references to their targets. 49107 49108 const { 49109 directives, 49110 bindings, 49111 references 49112 } = DirectiveBinder.apply(target.template, this.directiveMatcher); // Finally, run the TemplateBinder to bind references, variables, and other entities within the 49113 // template. This extracts all the metadata that doesn't depend on directive matching. 49114 49115 const { 49116 expressions, 49117 symbols, 49118 nestingLevel, 49119 usedPipes 49120 } = TemplateBinder.applyWithScope(target.template, scope); 49121 return new R3BoundTarget(target, directives, bindings, references, expressions, symbols, nestingLevel, templateEntities, usedPipes); 49122 } 49123 49124} 49125/** 49126 * Represents a binding scope within a template. 49127 * 49128 * Any variables, references, or other named entities declared within the template will 49129 * be captured and available by name in `namedEntities`. Additionally, child templates will 49130 * be analyzed and have their child `Scope`s available in `childScopes`. 49131 */ 49132 49133 49134class Scope { 49135 constructor(parentScope, template) { 49136 this.parentScope = parentScope; 49137 this.template = template; 49138 /** 49139 * Named members of the `Scope`, such as `Reference`s or `Variable`s. 49140 */ 49141 49142 this.namedEntities = new Map(); 49143 /** 49144 * Child `Scope`s for immediately nested `Template`s. 49145 */ 49146 49147 this.childScopes = new Map(); 49148 } 49149 49150 static newRootScope() { 49151 return new Scope(null, null); 49152 } 49153 /** 49154 * Process a template (either as a `Template` sub-template with variables, or a plain array of 49155 * template `Node`s) and construct its `Scope`. 49156 */ 49157 49158 49159 static apply(template) { 49160 const scope = Scope.newRootScope();
49161 scope.ingest(template); 49162 return scope; 49163 } 49164 /** 49165 * Internal method to process the template and populate the `Scope`. 49166 */ 49167 49168 49169 ingest(template) { 49170 if (template instanceof Template) { 49171 // Variables on an <ng-template> are defined in the inner scope. 49172 template.variables.forEach(node => this.visitVariable(node)); // Process the nodes of the template. 49173 49174 template.children.forEach(node => node.visit(this)); 49175 } else { 49176 // No overarching `Template` instance, so process the nodes directly. 49177 template.forEach(node => node.visit(this)); 49178 } 49179 } 49180 49181 visitElement(element) { 49182 // `Element`s in the template may have `Reference`s which are captured in the scope. 49183 element.references.forEach(node => this.visitReference(node)); // Recurse into the `Element`'s children. 49184 49185 element.children.forEach(node => node.visit(this)); 49186 } 49187 49188 visitTemplate(template) { 49189 // References on a <ng-template> are defined in the outer scope, so capture them before 49190 // processing the template's child scope. 49191 template.references.forEach(node => this.visitReference(node)); // Next, create an inner scope and process the template within it. 49192 49193 const scope = new Scope(this, template); 49194 scope.ingest(template); 49195 this.childScopes.set(template, scope); 49196 } 49197 49198 visitVariable(variable) { 49199 // Declare the variable if it's not already. 49200 this.maybeDeclare(variable); 49201 } 49202 49203 visitReference(reference) { 49204 // Declare the variable if it's not already. 49205 this.maybeDeclare(reference); 49206 } // Unused visitors. 49207 49208 49209 visitContent(content) {} 49210 49211 visitBoundAttribute(attr) {} 49212 49213 visitBoundEvent(event) {} 49214 49215 visitBoundText(text) {} 49216 49217 visitText(text) {} 49218 49219 visitTextAttribute(attr) {} 49220 49221 visitIcu(icu) {} 49222 49223 maybeDeclare(thing) { 49224 // Declare something with a name, as long as that name isn't taken. 49225 if (!this.namedEntities.has(thing.name)) { 49226 this.namedEntities.set(thing.name, thing); 49227 } 49228 } 49229 /** 49230 * Look up a variable within this `Scope`. 49231 * 49232 * This can recurse into a parent `Scope` if it's available. 49233 */ 49234 49235 49236 lookup(name) { 49237 if (this.namedEntities.has(name)) { 49238 // Found in the local scope. 49239 return this.namedEntities.get(name); 49240 } else if (this.parentScope !== null) { 49241 // Not in the local scope, but there's a parent scope so check there. 49242 return this.parentScope.lookup(name); 49243 } else { 49244 // At the top level and it wasn't found. 49245 return null; 49246 } 49247 } 49248 /** 49249 * Get the child scope for a `Template`. 49250 * 49251 * This should always be defined. 49252 */ 49253 49254 49255 getChildScope(template) { 49256 const res = this.childScopes.get(template); 49257 49258 if (res === undefined) { 49259 throw new Error(`Assertion error: child scope for ${template} not found`); 49260 } 49261 49262 return res; 49263 } 49264 49265} 49266/** 49267 * Processes a template and matches directives on nodes (elements and templates). 49268 * 49269 * Usually used via the static `apply()` method. 49270 */ 49271 49272 49273class DirectiveBinder { 49274 constructor(matcher, directives, bindings, references) { 49275 this.matcher = matcher; 49276 this.directives = directives; 49277 this.bindings = bindings; 49278 this.references = references; 49279 } 49280 /** 49281 * Process a template (list of `Node`s) and perform directive matching against each node. 49282 * 49283 * @param template the list of template `Node`s to match (recursively). 49284 * @param selectorMatcher a `SelectorMatcher` containing the directives that are in scope for 49285 * this template. 49286 * @returns three maps which contain information about directives in the template: the 49287 * `directives` map which lists directives matched on each node, the `bindings` map which 49288 * indicates which directives claimed which bindings (inputs, outputs, etc), and the `references` 49289 * map which resolves #references (`Reference`s) within the template to the named directive or 49290 * template node. 49291 */ 49292 49293 49294 static apply(template, selectorMatcher) { 49295 const directives = new Map(); 49296 const bindings = new Map(); 49297 const references = new Map(); 49298 const matcher = new DirectiveBinder(selectorMatcher, directives, bindings, references); 49299 matcher.ingest(template); 49300 return { 49301 directives, 49302 bindings, 49303 references 49304 }; 49305 } 49306 49307 ingest(template) { 49308 template.forEach(node =>
49308 node.visit(this)); 49309 } 49310 49311 visitElement(element) { 49312 this.visitElementOrTemplate(element.name, element); 49313 } 49314 49315 visitTemplate(template) { 49316 this.visitElementOrTemplate('ng-template', template); 49317 } 49318 49319 visitElementOrTemplate(elementName, node) { 49320 // First, determine the HTML shape of the node for the purpose of directive matching. 49321 // Do this by building up a `CssSelector` for the node. 49322 const cssSelector = createCssSelector(elementName, getAttrsForDirectiveMatching(node)); // Next, use the `SelectorMatcher` to get the list of directives on the node. 49323 49324 const directives = []; 49325 this.matcher.match(cssSelector, (_, directive) => directives.push(directive)); 49326 49327 if (directives.length > 0) { 49328 this.directives.set(node, directives); 49329 } // Resolve any references that are created on this node. 49330 49331 49332 node.references.forEach(ref => { 49333 let dirTarget = null; // If the reference expression is empty, then it matches the "primary" directive on the node 49334 // (if there is one). Otherwise it matches the host node itself (either an element or 49335 // <ng-template> node). 49336 49337 if (ref.value.trim() === '') { 49338 // This could be a reference to a component if there is one. 49339 dirTarget = directives.find(dir => dir.isComponent) || null; 49340 } else { 49341 // This should be a reference to a directive exported via exportAs. 49342 dirTarget = directives.find(dir => dir.exportAs !== null && dir.exportAs.some(value => value === ref.value)) || null; // Check if a matching directive was found. 49343 49344 if (dirTarget === null) { 49345 // No matching directive was found - this reference points to an unknown target. Leave it 49346 // unmapped. 49347 return; 49348 } 49349 } 49350 49351 if (dirTarget !== null) { 49352 // This reference points to a directive. 49353 this.references.set(ref, { 49354 directive: dirTarget, 49355 node 49356 }); 49357 } else { 49358 // This reference points to the node itself. 49359 this.references.set(ref, node); 49360 } 49361 }); 49362 49363 const setAttributeBinding = (attribute, ioType) => { 49364 const dir = directives.find(dir => dir[ioType].hasBindingPropertyName(attribute.name)); 49365 const binding = dir !== undefined ? dir : node; 49366 this.bindings.set(attribute, binding); 49367 }; // Node inputs (bound attributes) and text attributes can be bound to an 49368 // input on a directive. 49369 49370 49371 node.inputs.forEach(input => setAttributeBinding(input, 'inputs')); 49372 node.attributes.forEach(attr => setAttributeBinding(attr, 'inputs')); 49373 49374 if (node instanceof Template) { 49375 node.templateAttrs.forEach(attr => setAttributeBinding(attr, 'inputs')); 49376 } // Node outputs (bound events) can be bound to an output on a directive. 49377 49378 49379 node.outputs.forEach(output => setAttributeBinding(output, 'outputs')); // Recurse into the node's children. 49380 49381 node.children.forEach(child => child.visit(this)); 49382 } // Unused visitors. 49383 49384 49385 visitContent(content) {} 49386 49387 visitVariable(variable) {} 49388 49389 visitReference(reference) {} 49390 49391 visitTextAttribute(attribute) {} 49392 49393 visitBoundAttribute(attribute) {} 49394 49395 visitBoundEvent(attribute) {} 49396 49397 visitBoundAttributeOrEvent(node) {} 49398 49399 visitText(text) {} 49400 49401 visitBoundText(text) {} 49402 49403 visitIcu(icu) {} 49404 49405} 49406/** 49407 * Processes a template and extract metadata about expressions and symbols within. 49408 * 49409 * This is a companion to the `DirectiveBinder` that doesn't require knowledge of directives matched 49410 * within the template in order to operate. 49411 * 49412 * Expressions are visited by the superclass `RecursiveAstVisitor`, with custom logic provided 49413 * by overridden methods from that visitor. 49414 */ 49415 49416 49417class TemplateBinder extends RecursiveAstVisitor { 49418 constructor(bindings, symbols, usedPipes, nestingLevel, scope, template, level) { 49419 super(); 49420 this.bindings = bindings; 49421 this.symbols = symbols; 49422 this.usedPipes = usedPipes; 49423 this.nestingLevel = nestingLevel; 49424 this.scope = scope; 49425 this.template = template; 49426 this.level = level; 49427 this.pipesUsed = []; // Save a bit of processing time by constructing this closure in advance. 49428 49429 this.visitNode = node =>
49429 node.visit(this); 49430 } // This method is defined to reconcile the type of TemplateBinder since both 49431 // RecursiveAstVisitor and Visitor define the visit() method in their 49432 // interfaces. 49433 49434 49435 visit(node, context) { 49436 if (node instanceof AST) { 49437 node.visit(this, context); 49438 } else { 49439 node.visit(this); 49440 } 49441 } 49442 /** 49443 * Process a template and extract metadata about expressions and symbols within. 49444 * 49445 * @param template the nodes of the template to process 49446 * @param scope the `Scope` of the template being processed. 49447 * @returns three maps which contain metadata about the template: `expressions` which interprets 49448 * special `AST` nodes in expressions as pointing to references or variables declared within the 49449 * template, `symbols` which maps those variables and references to the nested `Template` which 49450 * declares them, if any, and `nestingLevel` which associates each `Template` with a integer 49451 * nesting level (how many levels deep within the template structure the `Template` is), starting 49452 * at 1. 49453 */ 49454 49455 49456 static applyWithScope(template, scope) { 49457 const expressions = new Map(); 49458 const symbols = new Map(); 49459 const nestingLevel = new Map(); 49460 const usedPipes = new Set(); // The top-level template has nesting level 0. 49461 49462 const binder = new TemplateBinder(expressions, symbols, usedPipes, nestingLevel, scope, template instanceof Template ? template : null, 0); 49463 binder.ingest(template); 49464 return { 49465 expressions, 49466 symbols, 49467 nestingLevel, 49468 usedPipes 49469 }; 49470 } 49471 49472 ingest(template) { 49473 if (template instanceof Template) { 49474 // For <ng-template>s, process only variables and child nodes. Inputs, outputs, templateAttrs, 49475 // and references were all processed in the scope of the containing template.
49476 template.variables.forEach(this.visitNode); 49477 template.children.forEach(this.visitNode); // Set the nesting level. 49478 49479 this.nestingLevel.set(template, this.level); 49480 } else { 49481 // Visit each node from the top-level template. 49482 template.forEach(this.visitNode); 49483 } 49484 } 49485 49486 visitElement(element) { 49487 // Visit the inputs, outputs, and children of the element. 49488 element.inputs.forEach(this.visitNode); 49489 element.outputs.forEach(this.visitNode); 49490 element.children.forEach(this.visitNode); 49491 } 49492 49493 visitTemplate(template) { 49494 // First, visit inputs, outputs and template attributes of the template node. 49495 template.inputs.forEach(this.visitNode); 49496 template.outputs.forEach(this.visitNode); 49497 template.templateAttrs.forEach(this.visitNode); // References are also evaluated in the outer context. 49498 49499 template.references.forEach(this.visitNode); // Next, recurse into the template using its scope, and bumping the nesting level up by one. 49500 49501 const childScope = this.scope.getChildScope(template); 49502 const binder = new TemplateBinder(this.bindings, this.symbols, this.usedPipes, this.nestingLevel, childScope, template, this.level + 1); 49503 binder.ingest(template); 49504 } 49505 49506 visitVariable(variable) { 49507 // Register the `Variable` as a symbol in the current `Template`. 49508 if (this.template !== null) { 49509 this.symbols.set(variable, this.template); 49510 } 49511 } 49512 49513 visitReference(reference) { 49514 // Register the `Reference` as a symbol in the current `Template`. 49515 if (this.template !== null) { 49516 this.symbols.set(reference, this.template); 49517 } 49518 } // Unused template visitors 49519 49520 49521 visitText(text) {} 49522 49523 visitContent(content) {} 49524 49525 visitTextAttribute(attribute) {} 49526 49527 visitIcu(icu) { 49528 Object.keys(icu.vars).forEach(key => icu.vars[key].visit(this)); 49529 Object.keys(icu.placeholders).forEach(key => icu.placeholders[key].visit(this)); 49530 } // The remaining visitors are concerned with processing AST expressions within template bindings 49531 49532 49533 visitBoundAttribute(attribute) { 49534 attribute.value.visit(this); 49535 } 49536 49537 visitBoundEvent(event) { 49538 event.handler.visit(this); 49539 } 49540 49541 visitBoundText(text) { 49542 text.value.visit(this); 49543 } 49544 49545 visitPipe(ast, context) { 49546 this.usedPipes.add(ast.name); 49547 return super.visitPipe(ast, context); 49548 } // These five types of AST expressions can refer to expression roots, which could be variables 49549 // or references in the current scope. 49550 49551 49552 visitPropertyRead(ast, context) { 49553 this.maybeMap(context, ast, ast.name); 49554 return super.visitPropertyRead(ast, context); 49555 } 49556 49557 visitSafePropertyRead(ast, context) { 49558 this.maybeMap(context, ast, ast.name); 49559 return super.visitSafePropertyRead(ast, context); 49560 } 49561 49562 visitPropertyWrite(ast, context) { 49563 this.maybeMap(context, ast, ast.name); 49564 return super.visitPropertyWrite(ast, context); 49565 } 49566 49567 maybeMap(scope, ast, name) { 49568 // If the receiver of the expression isn't the `ImplicitReceiver`, this isn't the root of an 49569 // `AST` expression that maps to a `Variable` or `Reference`. 49570 if (!(ast.receiver instanceof ImplicitReceiver)) { 49571 return; 49572 } // Check whether the name exists in the current scope. If so, map it. Otherwise, the name is 49573 // probably a property on the top-level component context. 49574 49575 49576 let target = this.scope.lookup(name); 49577 49578 if (target !== null) { 49579 this.bindings.set(ast, target); 49580 } 49581 } 49582 49583} 49584/** 49585 * Metadata container for a `Target` that allows queries for specific bits of metadata. 49586 * 49587 * See `BoundTarget` for documentation on the individual methods. 49588 */ 49589 49590 49591class R3BoundTarget { 49592 constructor(target, directives, bindings, references, exprTargets, symbols, nestingLevel, templateEntities, usedPipes) { 49593 this.target = target; 49594 this.directives = directives; 49595 this.bindings = bindings; 49596 this.references = references; 49597 this.exprTargets = exprTargets; 49598 this.symbols = symbols; 49599 this.nestingLevel = nestingLevel; 49600 this.templateEntities = templateEntities; 49601 this.usedPipes = usedPipes; 49602 } 49603 49604 getEntitiesInTemplateScope(template) { 49605 return this.templateEntities.get(template) ?? new Set(); 49606 } 49607 49608 getDirectivesOfNode(node) { 49609 return this.directives.get(node) || null; 49610 } 49611 49612 getReferenceTarget(ref) { 49613 return this.references.get(ref) || null; 49614 } 49615 49616 getConsumerOfBinding(binding) { 49617 return this.bindings.get(binding) || null; 49618 } 49619 49620 getExpressionTarget(expr) { 49621 return this.exprTargets.get(expr) || null; 49622 } 49623 49624 getTemplateOfSymbol(symbol) { 49625 return this.symbols.get(symbol) || null; 49626 } 49627 49628 getNestingLevel(template) { 49629 return this.nestingLevel.get(template) || 0; 49630 } 49631 49632 getUsedDirectives() { 49633 const set = new Set();
49634 this.directives.forEach(dirs => dirs.forEach(dir => set.add(dir))); 49635 return Array.from(set.values()); 49636 } 49637 49638 getUsedPipes() { 49639 return Array.from(this.usedPipes); 49640 } 49641 49642} 49643 49644function extractTemplateEntities(rootScope) { 49645 const entityMap = new Map(); 49646 49647 function extractScopeEntities(scope) { 49648 if (entityMap.has(scope.template)) { 49649 return entityMap.get(scope.template); 49650 } 49651 49652 const currentEntities = scope.namedEntities; 49653 let templateEntities; 49654 49655 if (scope.parentScope !== null) { 49656 templateEntities = new Map([...extractScopeEntities(scope.parentScope), ...currentEntities]); 49657 } else { 49658 templateEntities = new Map(currentEntities); 49659 } 49660 49661 entityMap.set(scope.template, templateEntities); 49662 return templateEntities; 49663 } 49664 49665 const scopesToProcess = [rootScope]; 49666 49667 while (scopesToProcess.length > 0) { 49668 const scope = scopesToProcess.pop(); 49669 49670 for (const childScope of scope.childScopes.values()) { 49671 scopesToProcess.push(childScope); 49672 } 49673 49674 extractScopeEntities(scope); 49675 } 49676 49677 const templateEntities = new Map(); 49678 49679 for (const [template, entities] of entityMap) { 49680 templateEntities.set(template, new Set(entities.values())); 49681 } 49682 49683 return templateEntities; 49684} 49685/** 49686 * @license 49687 * Copyright Google LLC All Rights Reserved. 49688 * 49689 * Use of this source code is governed by an MIT-style license that can be 49690 * found in the LICENSE file at https://angular.io/license 49691 */ 49692 49693 49694function compileClassMetadata(metadata) { 49695 // Generate an ngDevMode guarded call to setClassMetadata with the class identifier and its 49696 // metadata. 49697 const fnCall = importExpr(Identifiers.setClassMetadata).callFn([metadata.type, metadata.decorators, metadata.ctorParameters ?? literal(null), metadata.propDecorators ?? literal(null)]); 49698 const iife = fn([], [devOnlyGuardedExpression(fnCall).toStmt()]); 49699 return iife.callFn([]); 49700} 49701/** 49702 * @license 49703 * Copyright Google LLC All Rights Reserved. 49704 * 49705 * Use of this source code is governed by an MIT-style license that can be 49706 * found in the LICENSE file at https://angular.io/license 49707 */ 49708 49709/** 49710 * Every time we make a breaking change to the declaration interface or partial-linker behavior, we 49711 * must update this constant to prevent old partial-linkers from incorrectly processing the 49712 * declaration. 49713 * 49714 * Do not include any prerelease in these versions as they are ignored. 49715 */ 49716 49717 49718const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0'; 49719 49720function compileDeclareClassMetadata(metadata) { 49721 const definitionMap = new DefinitionMap(); 49722 definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6)); 49723 definitionMap.set('version', literal('14.2.10')); 49724 definitionMap.set('ngImport', importExpr(Identifiers.core)); 49725 definitionMap.set('type', metadata.type); 49726 definitionMap.set('decorators', metadata.decorators); 49727 definitionMap.set('ctorParameters', metadata.ctorParameters); 49728 definitionMap.set('propDecorators', metadata.propDecorators); 49729 return importExpr(Identifiers.declareClassMetadata).callFn([definitionMap.toLiteralMap()]); 49730} 49731/** 49732 * @license 49733 * Copyright Google LLC All Rights Reserved. 49734 * 49735 * Use of this source code is governed by an MIT-style license that can be 49736 * found in the LICENSE file at https://angular.io/license 49737 */ 49738 49739/** 49740 * Creates an array literal expression from the given array, mapping all values to an expression 49741 * using the provided mapping function. If the array is empty or null, then null is returned. 49742 * 49743 * @param values The array to transfer into literal array expression. 49744 * @param mapper The logic to use for creating an expression for the array's values. 49745 * @returns An array literal expression representing `values`, or null if `values` is empty or 49746 * is itself null. 49747 */ 49748 49749 49750function toOptionalLiteralArray(values, mapper) { 49751 if (values === null || values.length === 0) { 49752 return null; 49753 } 49754 49755 return literalArr(values.map(value => mapper(value))); 49756} 49757/** 49758 * Creates an object literal expression from the given object, mapping all values to an expression 49759 * using the provided mapping function. If the object has no keys, then null is returned. 49760 * 49761 * @param object The object to transfer into an object literal expression. 49762 * @param mapper The logic to use for creating an expression for the object's values. 49763 * @returns An object literal expression representing `object`, or null if `object` does not have 49764 * any keys. 49765 */ 49766 49767 49768function toOptionalLiteralMap(object, mapper) { 49769 const entries = Object.keys(object).map(key => { 49770 const value = object[key]; 49771 return { 49772 key, 49773 value: mapper(value), 49774 quoted: true 49775 }; 49776 }); 49777 49778 if (entries.length > 0) { 49779 return literalMap(entries); 49780 } else { 49781 return null; 49782 } 49783} 49784 49785function compileDependencies(deps) {
49786 if (deps === 'invalid') { 49787 // The `deps` can be set to the string "invalid" by the `unwrapConstructorDependencies()` 49788 // function, which tries to convert `ConstructorDeps` into `R3DependencyMetadata[]`. 49789 return literal('invalid'); 49790 } else if (deps === null) { 49791 return literal(null); 49792 } else { 49793 return literalArr(deps.map(compileDependency)); 49794 } 49795} 49796 49797function compileDependency(dep) { 49798 const depMeta = new DefinitionMap(); 49799 depMeta.set('token', dep.token); 49800 49801 if (dep.attributeNameType !== null) { 49802 depMeta.set('attribute', literal(true)); 49803 } 49804 49805 if (dep.host) { 49806 depMeta.set('host', literal(true)); 49807 } 49808 49809 if (dep.optional) { 49810 depMeta.set('optional', literal(true)); 49811 } 49812 49813 if (dep.self) { 49814 depMeta.set('self', literal(true)); 49815 } 49816 49817 if (dep.skipSelf) { 49818 depMeta.set('skipSelf', literal(true)); 49819 } 49820 49821 return depMeta.toLiteralMap(); 49822} 49823/** 49824 * @license 49825 * Copyright Google LLC All Rights Reserved. 49826 * 49827 * Use of this source code is governed by an MIT-style license that can be 49828 * found in the LICENSE file at https://angular.io/license 49829 */ 49830 49831/** 49832 * Every time we make a breaking change to the declaration interface or partial-linker behavior, we 49833 * must update this constant to prevent old partial-linkers from incorrectly processing the 49834 * declaration. 49835 * 49836 * Do not include any prerelease in these versions as they are ignored. 49837 */ 49838 49839 49840const MINIMUM_PARTIAL_LINKER_VERSION$5 = '14.0.0'; 49841/** 49842 * Compile a directive declaration defined by the `R3DirectiveMetadata`. 49843 */ 49844 49845function compileDeclareDirectiveFromMetadata(meta) { 49846 const definitionMap = createDirectiveDefinitionMap(meta); 49847 const expression = importExpr(Identifiers.declareDirective).callFn([definitionMap.toLiteralMap()]); 49848 const type = createDirectiveType(meta); 49849 return { 49850 expression, 49851 type, 49852 statements: [] 49853 }; 49854} 49855/** 49856 * Gathers the declaration fields for a directive into a `DefinitionMap`. This allows for reusing 49857 * this logic for components, as they extend the directive metadata. 49858 */ 49859 49860 49861function createDirectiveDefinitionMap(meta) { 49862 const definitionMap = new DefinitionMap(); 49863 definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5)); 49864 definitionMap.set('version', literal('14.2.10')); // e.g. `type: MyDirective` 49865 49866 definitionMap.set('type', meta.internalType); 49867 49868 if (meta.isStandalone) { 49869 definitionMap.set('isStandalone', literal(meta.isStandalone)); 49870 } // e.g. `selector: 'some-dir'` 49871 49872 49873 if (meta.selector !== null) { 49874 definitionMap.set('selector', literal(meta.selector)); 49875 } 49876 49877 definitionMap.set('inputs', conditionallyCreateMapObjectLiteral(meta.inputs, true)); 49878 definitionMap.set('outputs', conditionallyCreateMapObjectLiteral(meta.outputs)); 49879 definitionMap.set('host', compileHostMetadata(meta.host)); 49880 definitionMap.set('providers', meta.providers); 49881 49882 if (meta.queries.length > 0) { 49883 definitionMap.set('queries', literalArr(meta.queries.map(compileQuery))); 49884 } 49885 49886 if (meta.viewQueries.length > 0) { 49887 definitionMap.set('viewQueries', literalArr(meta.viewQueries.map(compileQuery))); 49888 } 49889 49890 if (meta.exportAs !== null) { 49891 definitionMap.set('exportAs', asLiteral(meta.exportAs)); 49892 } 49893 49894 if (meta.usesInheritance) { 49895 definitionMap.set('usesInheritance', literal(true)); 49896 } 49897 49898 if (meta.lifecycle.usesOnChanges) { 49899 definitionMap.set('usesOnChanges', literal(true)); 49900 } 49901 49902 definitionMap.set('ngImport', importExpr(Identifiers.core)); 49903 return definitionMap; 49904} 49905/** 49906 * Compiles the metadata of a single query into its partial declaration form as declared 49907 * by `R3DeclareQueryMetadata`. 49908 */ 49909 49910 49911function compileQuery(query) { 49912 const meta = new DefinitionMap(); 49913 meta.set('propertyName', literal(query.propertyName)); 49914 49915 if (query.first) { 49916 meta.set('first', literal(true)); 49917 } 49918 49919 meta.set('predicate', Array.isArray(query.predicate) ? asLiteral(query.predicate) : convertFromMaybeForwardRefExpression(query.predicate)); 49920 49921 if (!query.emitDistinctChangesOnly) { 49922 // `emitDistinctChangesOnly` is special because we expect it to be `true`. 49923 // Therefore we explicitly emit the field, and explicitly place it only when it's `false`. 49924 meta.set('emitDistinctChangesOnly', literal(false)); 49925 } else {// The linker will assume that an absent `emitDistinctChangesOnly` flag is by default `true`. 49926 } 49927 49928 if (query.descendants) { 49929 meta.set('descendants', literal(true)); 49930 } 49931 49932 meta.set('read', query.read); 49933 49934 if (query.static) { 49935 meta.set('static', literal(true)); 49936 } 49937 49938 return meta.toLiteralMap(); 49939} 49940/** 49941 * Compiles the host metadata into its partial declaration form as declared 49942 * in `R3DeclareDirectiveMetadata['host']` 49943 */ 49944 49945 49946function compileHostMetadata(meta) { 49947 const hostMetadata = new DefinitionMap(); 49948 hostMetadata.set('attributes', toOptionalLiteralMap(meta.attributes, expression => expression)); 49949 hostMetadata.set('listeners', toOptionalLiteralMap(meta.listeners, literal)); 49950 hostMetadata.set('properties', toOptionalLiteralMap(meta.properties, literal)); 49951 49952 if (meta.specialAttributes.styleAttr) { 49953 hostMetadata.set('styleAttribute', literal(meta.specialAttributes.styleAttr)); 49954 } 49955 49956 if (meta.specialAttributes.classAttr) { 49957 hostMetadata.set('classAttribute', literal(meta.specialAttributes.classAttr)); 49958 } 49959 49960 if (hostMetadata.values.length > 0) { 49961 return hostMetadata.toLiteralMap(); 49962 } else { 49963 return null; 49964 } 49965} 49966/** 49967 * @license 49968 * Copyright Google LLC All Rights Reserved. 49969 * 49970 * Use of this source code is governed by an MIT-style license that can be 49971 * found in the LICENSE file at https://angular.io/license 49972 */ 49973 49974/** 49975 * Compile a component declaration defined by the `R3ComponentMetadata`. 49976 */ 49977 49978 49979function compileDeclareComponentFromMetadata(meta, template, additionalTemplateInfo) { 49980 const definitionMap = createComponentDefinitionMap(meta, template, additionalTemplateInfo); 49981 const expression = importExpr(Identifiers.declareComponent).callFn([definitionMap.toLiteralMap()]); 49982 const type = createComponentType(meta); 49983 return { 49984 expression, 49985 type, 49986 statements: [] 49987 }; 49988} 49989/** 49990 * Gathers the declaration fields for a component into a `DefinitionMap`. 49991 */ 49992 49993 49994function createComponentDefinitionMap(meta, template, templateInfo) { 49995 const definitionMap = createDirectiveDefinitionMap(meta); 49996 definitionMap.set('template', getTemplateExpression(template, templateInfo)); 49997 49998 if (templateInfo.isInline) { 49999 definitionMap.set('isInline', literal(true)); 50000 } 50001 50002 definitionMap.set('styles', toOptionalLiteralArray(meta.styles, literal)); 50003 definitionMap.set('dependencies', compileUsedDependenciesMetadata(meta)); 50004 definitionMap.set('viewProviders', meta.viewProviders); 50005 definitionMap.set('animations', meta.animations); 50006 50007 if (meta.changeDetection !== undefined) { 50008 definitionMap.set('changeDetection', importExpr(Identifiers.ChangeDetectionStrategy).prop(ChangeDetectionStrategy[meta.changeDetection])); 50009 } 50010 50011 if (meta.encapsulation !== ViewEncapsulation.Emulated) { 50012 definitionMap.set('encapsulation', importExpr(Identifiers.ViewEncapsulation).prop(ViewEncapsulation[meta.encapsulation])); 50013 } 50014 50015 if (meta.interpolation !== DEFAULT_INTERPOLATION_CONFIG) { 50016 definitionMap.set('interpolation', literalArr([literal(meta.interpolation.start), literal(meta.interpolation.end)])); 50017 } 50018
50019 if (template.preserveWhitespaces === true) { 50020 definitionMap.set('preserveWhitespaces', literal(true)); 50021 } 50022 50023 return definitionMap; 50024} 50025 50026function getTemplateExpression(template, templateInfo) { 50027 // If the template has been defined using a direct literal, we use that expression directly 50028 // without any modifications. This is ensures proper source mapping from the partially 50029 // compiled code to the source file declaring the template. Note that this does not capture 50030 // template literals referenced indirectly through an identifier. 50031 if (templateInfo.inlineTemplateLiteralExpression !== null) { 50032 return templateInfo.inlineTemplateLiteralExpression; 50033 } // If the template is defined inline but not through a literal, the template has been resolved 50034 // through static interpretation. We create a literal but cannot provide any source span. Note 50035 // that we cannot use the expression defining the template because the linker expects the template 50036 // to be defined as a literal in the declaration. 50037 50038 50039 if (templateInfo.isInline) { 50040 return literal(templateInfo.content, null, null); 50041 } // The template is external so we must synthesize an expression node with 50042 // the appropriate source-span. 50043 50044 50045 const contents = templateInfo.content; 50046 const file = new ParseSourceFile(contents, templateInfo.sourceUrl); 50047 const start = new ParseLocation(file, 0, 0, 0); 50048 const end = computeEndLocation(file, contents); 50049 const span = new ParseSourceSpan(start, end); 50050 return literal(contents, null, span); 50051} 50052 50053function computeEndLocation(file, contents) { 50054 const length = contents.length; 50055 let lineStart = 0; 50056 let lastLineStart = 0; 50057 let line = 0; 50058 50059 do { 50060 lineStart = contents.indexOf('\n', lastLineStart); 50061 50062 if (lineStart !== -1) { 50063 lastLineStart = lineStart + 1; 50064 line++; 50065 } 50066 } while (lineStart !== -1); 50067 50068 return new ParseLocation(file, length, line, length - lastLineStart); 50069} 50070 50071function compileUsedDependenciesMetadata(meta) { 50072 const wrapType = meta.declarationListEmitMode !== 0 50073 /* DeclarationListEmitMode.Direct */ 50074 ? generateForwardRef : expr => expr; 50075 return toOptionalLiteralArray(meta.declarations, decl => { 50076 switch (decl.kind) { 50077 case R3TemplateDependencyKind.Directive: 50078 const dirMeta = new DefinitionMap(); 50079 dirMeta.set('kind', literal(decl.isComponent ? 'component' : 'directive')); 50080 dirMeta.set('type', wrapType(decl.type)); 50081 dirMeta.set('selector', literal(decl.selector)); 50082 dirMeta.set('inputs', toOptionalLiteralArray(decl.inputs, literal)); 50083 dirMeta.set('outputs', toOptionalLiteralArray(decl.outputs, literal)); 50084 dirMeta.set('exportAs', toOptionalLiteralArray(decl.exportAs, literal)); 50085 return dirMeta.toLiteralMap(); 50086 50087 case R3TemplateDependencyKind.Pipe: 50088 const pipeMeta = new DefinitionMap(); 50089 pipeMeta.set('kind', literal('pipe')); 50090 pipeMeta.set('type', wrapType(decl.type)); 50091 pipeMeta.set('name', literal(decl.name)); 50092 return pipeMeta.toLiteralMap(); 50093 50094 case R3TemplateDependencyKind.NgModule: 50095 const ngModuleMeta = new DefinitionMap(); 50096 ngModuleMeta.set('kind', literal('ngmodule')); 50097 ngModuleMeta.set('type', wrapType(decl.type)); 50098 return ngModuleMeta.toLiteralMap(); 50099 } 50100 }); 50101} 50102/** 50103 * @license 50104 * Copyright Google LLC All Rights Reserved. 50105 * 50106 * Use of this source code is governed by an MIT-style license that can be 50107 * found in the LICENSE file at https://angular.io/license 50108 */ 50109 50110/** 50111 * Every time we make a breaking change to the declaration interface or partial-linker behavior, we 50112 * must update this constant to prevent old partial-linkers from incorrectly processing the 50113 * declaration. 50114 * 50115 * Do not include any prerelease in these versions as they are ignored. 50116 */ 50117 50118 50119const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0'; 50120 50121function compileDeclareFactoryFunction(meta) { 50122 const definitionMap = new DefinitionMap(); 50123 definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4)); 50124 definitionMap.set('version', literal('14.2.10')); 50125 definitionMap.set('ngImport', importExpr(Identifiers.core)); 50126 definitionMap.set('type', meta.internalType); 50127 definitionMap.set('deps', compileDependencies(meta.deps)); 50128 definitionMap.set('target', importExpr(Identifiers.FactoryTarget).prop(FactoryTarget$1[meta.target])); 50129 return { 50130 expression: importExpr(Identifiers.declareFactory).callFn([definitionMap.toLiteralMap()]), 50131 statements: [], 50132 type: createFactoryType(meta) 50133 }; 50134} 50135/** 50136 * @license 50137 * Copyright Google LLC All Rights Reserved. 50138 * 50139 * Use of this source code is governed by an MIT-style license that can be 50140 * found in the LICENSE file at https://angular.io/license 50141 */ 50142 50143/** 50144 * Every time we make a breaking change to the declaration interface or partial-linker behavior, we 50145 * must update this constant to prevent old partial-linkers from incorrectly processing the 50146 * declaration. 50147 * 50148 * Do not include any prerelease in these versions as they are ignored. 50149 */ 50150 50151 50152const MINIMUM_PARTIAL_LINKER_VERSION$3 = '12.0.0'; 50153/** 50154 * Compile a Injectable declaration defined by the `R3InjectableMetadata`. 50155 */ 50156 50157function compileDeclareInjectableFromMetadata(meta) { 50158 const definitionMap = createInjectableDefinitionMap(meta); 50159 const expression = importExpr(Identifiers.declareInjectable).callFn([definitionMap.toLiteralMap()]); 50160 const type = createInjectableType(meta); 50161 return { 50162 expression, 50163 type, 50164 statements: [] 50165 }; 50166} 50167/** 50168 * Gathers the declaration fields for a Injectable into a `DefinitionMap`. 50169 */ 50170 50171 50172function createInjectableDefinitionMap(meta) { 50173 const definitionMap = new DefinitionMap(); 50174 definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3)); 50175 definitionMap.set('version', literal('14.2.10')); 50176 definitionMap.set('ngImport', importExpr(Identifiers.core)); 50177 definitionMap.set('type', meta.internalType); // Only generate providedIn property if it has a non-null value 50178 50179 if (meta.providedIn !== undefined) { 50180 const providedIn = convertFromMaybeForwardRefExpression(meta.providedIn); 50181 50182 if (providedIn.value !== null) { 50183 definitionMap.set('providedIn', providedIn); 50184 } 50185 } 50186 50187 if (meta.useClass !== undefined) { 50188 definitionMap.set('useClass', convertFromMaybeForwardRefExpression(meta.useClass)); 50189 } 50190 50191 if (meta.useExisting !== undefined) { 50192 definitionMap.set('useExisting', convertFromMaybeForwardRefExpression(meta.useExisting)); 50193 } 50194 50195 if (meta.useValue !== undefined) { 50196 definitionMap.set('useValue', convertFromMaybeForwardRefExpression(meta.useValue)); 50197 } // Factories do not contain `ForwardRef`s since any types are already wrapped in a function call 50198 // so the types will not be eagerly evaluated. Therefore we do not need to process this expression 50199 // with `convertFromProviderExpression()`. 50200 50201 50202 if (meta.useFactory !== undefined) { 50203 definitionMap.set('useFactory', meta.useFactory); 50204 } 50205 50206 if (meta.deps !== undefined) { 50207 definitionMap.set('deps', literalArr(meta.deps.map(compileDependency))); 50208 } 50209 50210 return definitionMap; 50211} 50212/** 50213 * @license 50214 * Copyright Google LLC All Rights Reserved. 50215 * 50216 * Use of this source code is governed by an MIT-style license that can be 50217 * found in the LICENSE file at https://angular.io/license 50218 */ 50219 50220/** 50221 * Every time we make a breaking change to the declaration interface or partial-linker behavior, we 50222 * must update this constant to prevent old partial-linkers from incorrectly processing the 50223 * declaration. 50224 * 50225 * Do not include any prerelease in these versions as they are ignored. 50226 */ 50227 50228 50229const MINIMUM_PARTIAL_LINKER_VERSION$2 = '12.0.0'; 50230 50231function compileDeclareInjectorFromMetadata(meta) { 50232 const definitionMap = createInjectorDefinitionMap(meta); 50233 const expression = importExpr(Identifiers.declareInjector).callFn([definitionMap.toLiteralMap()]); 50234 const type = createInjectorType(meta); 50235 return { 50236 expression, 50237 type, 50238 statements: [] 50239 }; 50240} 50241/** 50242 * Gathers the declaration fields for an Injector into a `DefinitionMap`. 50243 */ 50244 50245 50246function createInjectorDefinitionMap(meta) { 50247 const definitionMap = new DefinitionMap(); 50248 definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2)); 50249 definitionMap.set('version', literal('14.2.10')); 50250 definitionMap.set('ngImport', importExpr(Identifiers.core)); 50251 definitionMap.set('type', meta.internalType); 50252 definitionMap.set('providers', meta.providers); 50253 50254 if (meta.imports.length > 0) { 50255 definitionMap.set('imports', literalArr(meta.imports)); 50256 } 50257 50258 return definitionMap; 50259} 50260/** 50261 * @license 50262 * Copyright Google LLC All Rights Reserved. 50263 * 50264 * Use of this source code is governed by an MIT-style license that can be 50265 * found in the LICENSE file at https://angular.io/license 50266 */ 50267 50268/** 50269 * Every time we make a breaking change to the declaration interface or partial-linker behavior, we 50270 * must update this constant to prevent old partial-linkers from incorrectly processing the 50271 * declaration. 50272 * 50273 * Do not include any prerelease in these versions as they are ignored. 50274 */ 50275 50276 50277const MINIMUM_PARTIAL_LINKER_VERSION$1 = '14.0.0'; 50278 50279function compileDeclareNgModuleFromMetadata(meta) { 50280 const definitionMap = createNgModuleDefinitionMap(meta); 50281 const expression = importExpr(Identifiers.declareNgModule).callFn([definitionMap.toLiteralMap()]); 50282 const type = createNgModuleType(meta); 50283 return { 50284 expression, 50285 type, 50286 statements: [] 50287 }; 50288} 50289/** 50290 * Gathers the declaration fields for an NgModule into a `DefinitionMap`. 50291 */ 50292 50293 50294function createNgModuleDefinitionMap(meta) { 50295 const definitionMap = new DefinitionMap(); 50296 definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1)); 50297 definitionMap.set('version', literal('14.2.10')); 50298 definitionMap.set('ngImport', importExpr(Identifiers.core)); 50299 definitionMap.set('type', meta.internalType); // We only generate the keys in the metadata if the arrays contain values. 50300 // We must wrap the arrays inside a function if any of the values are a forward reference to a 50301 // not-yet-declared class. This is to support JIT execution of the `ɵɵngDeclareNgModule(
50301)` call. 50302 // In the linker these wrappers are stripped and then reapplied for the `ɵɵdefineNgModule()` call. 50303 50304 if (meta.bootstrap.length > 0) { 50305 definitionMap.set('bootstrap', refsToArray(meta.bootstrap, meta.containsForwardDecls)); 50306 } 50307 50308 if (meta.declarations.length > 0) { 50309 definitionMap.set('declarations', refsToArray(meta.declarations, meta.containsForwardDecls)); 50310 } 50311 50312 if (meta.imports.length > 0) { 50313 definitionMap.set('imports', refsToArray(meta.imports, meta.containsForwardDecls)); 50314 } 50315 50316 if (meta.exports.length > 0) { 50317 definitionMap.set('exports', refsToArray(meta.exports, meta.containsForwardDecls)); 50318 } 50319 50320 if (meta.schemas !== null && meta.schemas.length > 0) { 50321 definitionMap.set('schemas', literalArr(meta.schemas.map(ref => ref.value))); 50322 } 50323 50324 if (meta.id !== null) { 50325 definitionMap.set('id', meta.id); 50326 } 50327 50328 return definitionMap; 50329} 50330/** 50331 * @license 50332 * Copyright Google LLC All Rights Reserved. 50333 * 50334 * Use of this source code is governed by an MIT-style license that can be 50335 * found in the LICENSE file at https://angular.io/license 50336 */ 50337 50338/** 50339 * Every time we make a breaking change to the declaration interface or partial-linker behavior, we 50340 * must update this constant to prevent old partial-linkers from incorrectly processing the 50341 * declaration. 50342 * 50343 * Do not include any prerelease in these versions as they are ignored. 50344 */ 50345 50346 50347const MINIMUM_PARTIAL_LINKER_VERSION = '14.0.0'; 50348/** 50349 * Compile a Pipe declaration defined by the `R3PipeMetadata`. 50350 */ 50351 50352function compileDeclarePipeFromMetadata(meta) { 50353 const definitionMap = createPipeDefinitionMap(meta); 50354 const expression = importExpr(Identifiers.declarePipe).callFn([definitionMap.toLiteralMap()]); 50355 const type = createPipeType(meta); 50356 return { 50357 expression, 50358 type, 50359 statements: [] 50360 }; 50361} 50362/** 50363 * Gathers the declaration fields for a Pipe into a `DefinitionMap`. 50364 */ 50365 50366 50367function createPipeDefinitionMap(meta) { 50368 const definitionMap = new DefinitionMap(); 50369 definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION)); 50370 definitionMap.set('version', literal('14.2.10')); 50371 definitionMap.set('ngImport', importExpr(Identifiers.core)); // e.g. `type: MyPipe` 50372 50373 definitionMap.set('type', meta.internalType); 50374 50375 if (meta.isStandalone) { 50376 definitionMap.set('isStandalone', literal(meta.isStandalone)); 50377 } // e.g. `name: "myPipe"` 50378 50379 50380 definitionMap.set('name', literal(meta.pipeName)); 50381 50382 if (meta.pure === false) { 50383 // e.g. `pure: false` 50384 definitionMap.set('pure', literal(meta.pure)); 50385 } 50386 50387 return definitionMap; 50388} 50389/** 50390 * @license 50391 * Copyright Google LLC All Rights Reserved. 50392 * 50393 * Use of this source code is governed by an MIT-style license that can be 50394 * found in the LICENSE file at https://angular.io/license 50395 */ 50396// This file only reexports content of the `src` folder. Keep it that way. 50397// This function call has a global side effects and publishes the compiler into global namespace for 50398// the late binding of the Compiler to the @angular/core for jit compilation. 50399 50400 50401publishFacade(_global); 50402/** 50403 * @license 50404 * Copyright Google LLC All Rights Reserved. 50405 * 50406 * Use of this source code is governed by an MIT-style license that can be 50407 * found in the LICENSE file at https://angular.io/license 50408 */ 50409// This file only reexports content of the `src` folder. Keep it that way. 50410 50411/** 50412 * @license 50413 * Copyright Google LLC All Rights Reserved. 50414 * 50415 * Use of this source code is governed by an MIT-style license that can be 50416 * found in the LICENSE file at https://angular.io/license 50417 */ 50418 50419/** 50420 * @license 50421 * Copyright Google LLC All Rights Reserved. 50422 * 50423 * Use of this source code is governed by an MIT-style license that can be 50424 * found in the LICENSE file at https://angular.io/license 50425 */ 50426 50427 50428 50429/***/ }), 50430 50431/***/ 2560: 50432/*!******************************************************!*\ 50433 !*** ./node_modules/@angular/core/fesm2020/core.mjs ***! 50434 \******************************************************/ 50435/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 50436 50437__webpack_require__.r(__webpack_exports__); 50438/* harmony export */ __webpack_require__.d(__webpack_exports__, { 50439/* harmony export */ "ANALYZE_FOR_ENTRY_COMPONENTS": () => (/* binding */ ANALYZE_FOR_ENTRY_COMPONENTS), 50440/* harmony export */ "ANIMATION_MODULE_TYPE": () => (/* binding */ ANIMATION_MODULE_TYPE), 50441/* harmony export */ "APP_BOOTSTRAP_LISTENER": () => (/* binding */ APP_BOOTSTRAP_LISTENER), 50442/* harmony export */ "APP_ID": () => (/* binding */ APP_ID), 50443/* harmony export */ "APP_INITIALIZER": () => (/* binding */ APP_INITIALIZER), 50444/* harmony export */ "ApplicationInitStatus": () => (/* binding */ ApplicationInitStatus), 50445/* harmony export */ "ApplicationModule": () => (/* binding */ ApplicationModule), 50446/* harmony export */ "ApplicationRef": () => (/* binding */ ApplicationRef), 50447/* harmony export */ "Attribute": () => (/* binding */ Attribute), 50448/* harmony export */ "COMPILER_OPTIONS": () => (/* binding */ COMPILER_OPTIONS), 50449/* harmony export */ "CUSTOM_ELEMENTS_SCHEMA": () => (/* binding */ CUSTOM_ELEMENTS_SCHEMA), 50450/* harmony export */ "ChangeDetectionStrategy": () => (/* binding */ ChangeDetectionStrategy), 50451/* harmony export */ "ChangeDetectorRef": () => (/* binding */ ChangeDetectorRef), 50452/* harmony export */ "Compiler": () => (/* binding */ Compiler), 50453/* harmony export */ "CompilerFactory": () => (/* binding */ CompilerFactory), 50454/* harmony export */ "Component": () => (/* binding */ Component), 50455/* harmony export */ "ComponentFactory": () => (/* binding */ ComponentFactory$1), 50456/* harmony export */ "ComponentFactoryResolver": () => (/* binding */ ComponentFactoryResolver$1), 50457/* harmony export */ "ComponentRef": () => (/* binding */ ComponentRef$1), 50458/* harmony export */ "ContentChild": () => (/* binding */ ContentChild), 50459/* harmony export */ "ContentChildren": () => (/* binding */ ContentChildren), 50460/* harmony export */ "DEFAULT_CURRENCY_CODE": () => (/* binding */ DEFAULT_CURRENCY_CODE), 50461/* harmony export */ "DebugElement": () => (/* binding */ DebugElement), 50462/* harmony export */ "DebugEventListener": () => (/* binding */ DebugEventListener), 50463/* harmony export */ "DebugNode": () => (/* binding */ DebugNode), 50464/* harmony export */ "DefaultIterableDiffer": () => (/* binding */ DefaultIterableDiffer), 50465/* harmony export */ "Directive": () => (/* binding */ Directive), 50466/* harmony export */ "ENVIRONMENT_INITIALIZER": () => (/* binding */ ENVIRONMENT_INITIALIZER), 50467/* harmony export */ "ElementRef": () => (/* binding */ ElementRef), 50468/* harmony export */ "EmbeddedViewRef": () => (/* binding */ EmbeddedViewRef), 50469/* harmony export */ "EnvironmentInjector": () => (/* binding */ EnvironmentInjector), 50470/* harmony export */ "ErrorHandler": () => (/* binding */ ErrorHandler), 50471/* harmony export */ "EventEmitter": () => (/* binding */ EventEmitter), 50472/* harmony export */ "Host": () => (/* binding */ Host), 50473/* harmony export */ "HostBinding": () => (/* binding */ HostBinding),
50474/* harmony export */ "HostListener": () => (/* binding */ HostListener), 50475/* harmony export */ "INJECTOR": () => (/* binding */ INJECTOR), 50476/* harmony export */ "Inject": () => (/* binding */ Inject), 50477/* harmony export */ "InjectFlags": () => (/* binding */ InjectFlags), 50478/* harmony export */ "Injectable": () => (/* binding */ Injectable), 50479/* harmony export */ "InjectionToken": () => (/* binding */ InjectionToken), 50480/* harmony export */ "Injector": () => (/* binding */ Injector), 50481/* harmony export */ "Input": () => (/* binding */ Input), 50482/* harmony export */ "IterableDiffers": () => (/* binding */ IterableDiffers), 50483/* harmony export */ "KeyValueDiffers": () => (/* binding */ KeyValueDiffers), 50484/* harmony export */ "LOCALE_ID": () => (/* binding */ LOCALE_ID), 50485/* harmony export */ "MissingTranslationStrategy": () => (/* binding */ MissingTranslationStrategy), 50486/* harmony export */ "ModuleWithComponentFactories": () => (/* binding */ ModuleWithComponentFactories), 50487/* harmony export */ "NO_ERRORS_SCHEMA": () => (/* binding */ NO_ERRORS_SCHEMA), 50488/* harmony export */ "NgModule": () => (/* binding */ NgModule), 50489/* harmony export */ "NgModuleFactory": () => (/* binding */ NgModuleFactory$1), 50490/* harmony export */ "NgModuleRef": () => (/* binding */ NgModuleRef$1), 50491/* harmony export */ "NgProbeToken": () => (/* binding */ NgProbeToken), 50492/* harmony export */ "NgZone": () => (/* binding */ NgZone), 50493/* harmony export */ "Optional": () => (/* binding */ Optional), 50494/* harmony export */ "Output": () => (/* binding */ Output), 50495/* harmony export */ "PACKAGE_ROOT_URL": () => (/* binding */ PACKAGE_ROOT_URL), 50496/* harmony export */ "PLATFORM_ID": () => (/* binding */ PLATFORM_ID), 50497/* harmony export */ "PLATFORM_INITIALIZER": () => (/* binding */ PLATFORM_INITIALIZER), 50498/* harmony export */ "Pipe": () => (/* binding */ Pipe), 50499/* harmony export */ "PlatformRef": () => (/* binding */ PlatformRef), 50500/* harmony export */ "Query": () => (/* binding */ Query), 50501/* harmony export */ "QueryList": () => (/* binding */ QueryList), 50502/* harmony export */ "ReflectiveInjector": () => (/* binding */ ReflectiveInjector), 50503/* harmony export */ "ReflectiveKey": () => (/* binding */ ReflectiveKey), 50504/* harmony export */ "Renderer2": () => (/* binding */ Renderer2), 50505/* harmony export */ "RendererFactory2": () => (/* binding */ RendererFactory2), 50506/* harmony export */ "RendererStyleFlags2": () => (/* binding */ RendererStyleFlags2), 50507/* harmony export */ "ResolvedReflectiveFactory": () => (/* binding */ ResolvedReflectiveFactory), 50508/* harmony export */ "Sanitizer": () => (/* binding */ Sanitizer), 50509/* harmony export */ "SecurityContext": () => (/* binding */ SecurityContext), 50510/* harmony export */ "Self": () => (/* binding */ Self), 50511/* harmony export */ "SimpleChange": () => (/* binding */ SimpleChange), 50512/* harmony export */ "SkipSelf": () => (/* binding */ SkipSelf), 50513/* harmony export */ "TRANSLATIONS": () => (/* binding */ TRANSLATIONS), 50514/* harmony export */ "TRANSLATIONS_FORMAT": () => (/* binding */ TRANSLATIONS_FORMAT), 50515/* harmony export */ "TemplateRef": () => (/* binding */ TemplateRef), 50516/* harmony export */ "Testability": () => (/* binding */ Testability), 50517/* harmony export */ "TestabilityRegistry": () => (/* binding */ TestabilityRegistry), 50518/* harmony export */ "Type": () => (/* binding */ Type), 50519/* harmony export */ "VERSION": () => (/* binding */ VERSION), 50520/* harmony export */ "Version": () => (/* binding */ Version), 50521/* harmony export */ "ViewChild": () => (/* binding */ ViewChild), 50522/* harmony export */ "ViewChildren": () => (/* binding */ ViewChildren), 50523/* harmony export */ "ViewContainerRef": () => (/* binding */ ViewContainerRef), 50524/* harmony export */ "ViewEncapsulation": () => (/* binding */ ViewEncapsulation$1), 50525/* harmony export */ "ViewRef": () => (/* binding */ ViewRef), 50526/* harmony export */ "asNativeElements": () => (/* binding */ asNativeElements), 50527/* harmony export */ "assertPlatform": () => (/* binding */ assertPlatform), 50528/* harmony export */ "createComponent": () => (/* binding */ createComponent), 50529/* harmony export */ "createEnvironmentInjector": () => (/* binding */ createEnvironmentInjector), 50530/* harmony export */ "createNgModule": () => (/* binding */ createNgModule), 50531/* harmony export */ "createNgModuleRef": () => (/* binding */ createNgModuleRef), 50532/* harmony export */ "createPlatform": () => (/* binding */ createPlatform), 50533/* harmony export */ "createPlatformFactory": () => (/* binding */ createPlatformFactory), 50534/* harmony export */ "defineInjectable": () => (/* binding */ defineInjectable), 50535/* harmony export */ "destroyPlatform": () => (/* binding */ destroyPlatform), 50536/* harmony export */ "enableProdMode": () => (/* binding */ enableProdMode), 50537/* harmony export */ "forwardRef": () => (/* binding */ forwardRef), 50538/* harmony export */ "getDebugNode": () => (/* binding */ getDebugNode), 50539/* harmony export */ "getModuleFactory": () => (/* binding */ getModuleFactory), 50540/* harmony export */ "getNgModuleById": () => (/* binding */ getNgModuleById), 50541/* harmony export */ "getPlatform": () => (/* binding */ getPlatform), 50542/* harmony export */ "importProvidersFrom": () => (/* binding */ importProvidersFrom), 50543/* harmony export */ "inject": () => (/* binding */ inject), 50544/* harmony export */ "isDevMode": () => (/* binding */ isDevMode), 50545/* harmony export */ "platformCore": () => (/* binding */ platformCore),
50546/* harmony export */ "reflectComponentType": () => (/* binding */ reflectComponentType), 50547/* harmony export */ "resolveForwardRef": () => (/* binding */ resolveForwardRef), 50548/* harmony export */ "setTestabilityGetter": () => (/* binding */ setTestabilityGetter), 50549/* harmony export */ "ɵALLOW_MULTIPLE_PLATFORMS": () => (/* binding */ ALLOW_MULTIPLE_PLATFORMS), 50550/* harmony export */ "ɵAPP_ID_RANDOM_PROVIDER": () => (/* binding */ APP_ID_RANDOM_PROVIDER), 50551/* harmony export */ "ɵChangeDetectorStatus": () => (/* binding */ ChangeDetectorStatus), 50552/* harmony export */ "ɵComponentFactory": () => (/* binding */ ComponentFactory$1), 50553/* harmony export */ "ɵConsole": () => (/* binding */ Console), 50554/* harmony export */ "ɵDEFAULT_LOCALE_ID": () => (/* binding */ DEFAULT_LOCALE_ID), 50555/* harmony export */ "ɵINJECTOR_SCOPE": () => (/* binding */ INJECTOR_SCOPE), 50556/* harmony export */ "ɵLContext": () => (/* binding */ LContext), 50557/* harmony export */ "ɵLifecycleHooksFeature": () => (/* binding */ LifecycleHooksFeature), 50558/* harmony export */ "ɵLocaleDataIndex": () => (/* binding */ LocaleDataIndex), 50559/* harmony export */ "ɵNG_COMP_DEF": () => (/* binding */ NG_COMP_DEF), 50560/* harmony export */ "ɵNG_DIR_DEF": () => (/* binding */ NG_DIR_DEF), 50561/* harmony export */ "ɵNG_ELEMENT_ID": () => (/* binding */ NG_ELEMENT_ID), 50562/* harmony export */ "ɵNG_INJ_DEF": () => (/* binding */ NG_INJ_DEF), 50563/* harmony export */ "ɵNG_MOD_DEF": () => (/* binding */ NG_MOD_DEF), 50564/* harmony export */ "ɵNG_PIPE_DEF": () => (/* binding */ NG_PIPE_DEF), 50565/* harmony export */ "ɵNG_PROV_DEF": () => (/* binding */ NG_PROV_DEF), 50566/* harmony export */ "ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR": () => (/* binding */ NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR), 50567/* harmony export */ "ɵNO_CHANGE": () => (/* binding */ NO_CHANGE), 50568/* harmony export */ "ɵNgModuleFactory": () => (/* binding */ NgModuleFactory), 50569/* harmony export */ "ɵNoopNgZone": () => (/* binding */ NoopNgZone), 50570/* harmony export */ "ɵReflectionCapabilities": () => (/* binding */ ReflectionCapabilities), 50571/* harmony export */ "ɵRender3ComponentFactory": () => (/* binding */ ComponentFactory), 50572/* harmony export */ "ɵRender3ComponentRef": () => (/* binding */ ComponentRef), 50573/* harmony export */ "ɵRender3NgModuleRef": () => (/* binding */ NgModuleRef), 50574/* harmony export */ "ɵRuntimeError": () => (/* binding */ RuntimeError), 50575/* harmony export */ "ɵTESTABILITY": () => (/* binding */ TESTABILITY), 50576/* harmony export */ "ɵTESTABILITY_GETTER": () => (/* binding */ TESTABILITY_GETTER), 50577/* harmony export */ "ɵViewRef": () => (/* binding */ ViewRef$1), 50578/* harmony export */ "ɵ_sanitizeHtml": () => (/* binding */ _sanitizeHtml),
50579/* harmony export */ "ɵ_sanitizeUrl": () => (/* binding */ _sanitizeUrl), 50580/* harmony export */ "ɵallowSanitizationBypassAndThrow": () => (/* binding */ allowSanitizationBypassAndThrow), 50581/* harmony export */ "ɵbypassSanitizationTrustHtml": () => (/* binding */ bypassSanitizationTrustHtml), 50582/* harmony export */ "ɵbypassSanitizationTrustResourceUrl": () => (/* binding */ bypassSanitizationTrustResourceUrl), 50583/* harmony export */ "ɵbypassSanitizationTrustScript": () => (/* binding */ bypassSanitizationTrustScript), 50584/* harmony export */ "ɵbypassSanitizationTrustStyle": () => (/* binding */ bypassSanitizationTrustStyle), 50585/* harmony export */ "ɵbypassSanitizationTrustUrl": () => (/* binding */ bypassSanitizationTrustUrl), 50586/* harmony export */ "ɵclearResolutionOfComponentResourcesQueue": () => (/* binding */ clearResolutionOfComponentResourcesQueue), 50587/* harmony export */ "ɵcoerceToBoolean": () => (/* binding */ coerceToBoolean), 50588/* harmony export */ "ɵcompileComponent": () => (/* binding */ compileComponent), 50589/* harmony export */ "ɵcompileDirective": () => (/* binding */ compileDirective), 50590/* harmony export */ "ɵcompileNgModule": () => (/* binding */ compileNgModule), 50591/* harmony export */ "ɵcompileNgModuleDefs": () => (/* binding */ compileNgModuleDefs), 50592/* harmony export */ "ɵcompileNgModuleFactory": () => (/* binding */ compileNgModuleFactory), 50593/* harmony export */ "ɵcompilePipe": () => (/* binding */ compilePipe), 50594/* harmony export */ "ɵcreateInjector": () => (/* binding */ createInjector), 50595/* harmony export */ "ɵdefaultIterableDiffers": () => (/* binding */ defaultIterableDiffers), 50596/* harmony export */ "ɵdefaultKeyValueDiffers": () => (/* binding */ defaultKeyValueDiffers), 50597/* harmony export */ "ɵdetectChanges": () => (/* binding */ detectChanges), 50598/* harmony export */ "ɵdevModeEqual": () => (/* binding */ devModeEqual), 50599/* harmony export */ "ɵfindLocaleData": () => (/* binding */ findLocaleData), 50600/* harmony export */ "ɵflushModuleScopingQueueAsMuchAsPossible": () => (/* binding */ flushModuleScopingQueueAsMuchAsPossible), 50601/* harmony export */ "ɵformatRuntimeError": () => (/* binding */ formatRuntimeError), 50602/* harmony export */ "ɵgetDebugNode": () => (/* binding */ getDebugNode), 50603/* harmony export */ "ɵgetDebugNodeR2": () => (/* binding */ getDebugNodeR2), 50604/* harmony export */ "ɵgetDirectives": () => (/* binding */ getDirectives), 50605/* harmony export */ "ɵgetHostElement": () => (/* binding */ getHostElement), 50606/* harmony export */ "ɵgetInjectableDef": () => (/* binding */ getInjectableDef), 50607/* harmony export */ "ɵgetLContext": () => (/* binding */ getLContext), 50608/* harmony export */ "ɵgetLocaleCurrencyCode": () => (/* binding */ getLocaleCurrencyCode), 50609/* harmony export */ "ɵgetLocalePluralCase": () => (/* binding */ getLocalePluralCase), 50610/* harmony export */ "ɵgetSanitizationBypassType": () => (/* binding */ getSanitizationBypassType), 50611/* harmony export */ "ɵgetUnknownElementStrictMode": () => (/* binding */ ɵgetUnknownElementStrictMode), 50612/* harmony export */ "ɵgetUnknownPropertyStrictMode": () => (/* binding */ ɵgetUnknownPropertyStrictMode), 50613/* harmony export */ "ɵglobal": () => (/* binding */ _global), 50614/* harmony export */ "ɵinjectChangeDetectorRef": () => (/* binding */ injectChangeDetectorRef), 50615/* harmony export */ "ɵinternalCreateApplication": () => (/* binding */ internalCreateApplication), 50616/* harmony export */ "ɵisBoundToModule": () => (/* binding */ isBoundToModule), 50617/* harmony export */ "ɵisDefaultChangeDetectionStrategy": () => (/* binding */ isDefaultChangeDetectionStrategy), 50618/* harmony export */ "ɵisInjectable": () => (/* binding */ isInjectable), 50619/* harmony export */ "ɵisListLikeIterable": () => (/* binding */ isListLikeIterable), 50620/* harmony export */ "ɵisObservable": () => (/* binding */ isObservable), 50621/* harmony export */ "ɵisPromise": () => (/* binding */ isPromise), 50622/* harmony export */ "ɵisStandalone": () => (/* binding */ isStandalone), 50623/* harmony export */ "ɵisSubscribable": () => (/* binding */ isSubscribable), 50624/* harmony export */ "ɵivyEnabled": () => (/* binding */ ɵivyEnabled), 50625/* harmony export */ "ɵmakeDecorator": () => (/* binding */ makeDecorator), 50626/* harmony export */ "ɵnoSideEffects": () => (/* binding */ noSideEffects), 50627/* harmony export */ "ɵpatchComponentDefWithScope": () => (/* binding */ patchComponentDefWithScope), 50628/* harmony export */ "ɵpublishDefaultGlobalUtils": () => (/* binding */ publishDefaultGlobalUtils$1), 50629/* harmony export */ "ɵpublishGlobalUtil": () => (/* binding */ publishGlobalUtil), 50630/* harmony export */ "ɵregisterLocaleData": () => (/* binding */ registerLocaleData), 50631/* harmony export */ "ɵresetCompiledComponents": () => (/* binding */ resetCompiledComponents), 50632/* harmony export */ "ɵresetJitOptions": () => (/* binding */ resetJitOptions), 50633/* harmony export */ "ɵresolveComponentResources": () =>
50633 (/* binding */ resolveComponentResources), 50634/* harmony export */ "ɵsetAllowDuplicateNgModuleIdsForTest": () => (/* binding */ setAllowDuplicateNgModuleIdsForTest), 50635/* harmony export */ "ɵsetClassMetadata": () => (/* binding */ setClassMetadata), 50636/* harmony export */ "ɵsetCurrentInjector": () => (/* binding */ setCurrentInjector), 50637/* harmony export */ "ɵsetDocument": () => (/* binding */ setDocument), 50638/* harmony export */ "ɵsetLocaleId": () => (/* binding */ setLocaleId), 50639/* harmony export */ "ɵsetUnknownElementStrictMode": () => (/* binding */ ɵsetUnknownElementStrictMode), 50640/* harmony export */ "ɵsetUnknownPropertyStrictMode": () => (/* binding */ ɵsetUnknownPropertyStrictMode), 50641/* harmony export */ "ɵstore": () => (/* binding */ store), 50642/* harmony export */ "ɵstringify": () => (/* binding */ stringify), 50643/* harmony export */ "ɵtransitiveScopesFor": () => (/* binding */ transitiveScopesFor), 50644/* harmony export */ "ɵunregisterLocaleData": () => (/* binding */ unregisterAllLocaleData), 50645/* harmony export */ "ɵunwrapSafeValue": () => (/* binding */ unwrapSafeValue), 50646/* harmony export */ "ɵɵCopyDefinitionFeature": () => (/* binding */ ɵɵCopyDefinitionFeature), 50647/* harmony export */ "ɵɵFactoryTarget": () => (/* binding */ FactoryTarget), 50648/* harmony export */ "ɵɵInheritDefinitionFeature": () => (/* binding */ ɵɵInheritDefinitionFeature), 50649/* harmony export */ "ɵɵNgOnChangesFeature": () => (/* binding */ ɵɵNgOnChangesFeature), 50650/* harmony export */ "ɵɵProvidersFeature": () => (/* binding */ ɵɵProvidersFeature), 50651/* harmony export */ "ɵɵStandaloneFeature": () => (/* binding */ ɵɵStandaloneFeature), 50652/* harmony export */ "ɵɵadvance": () => (/* binding */ ɵɵadvance), 50653/* harmony export */ "ɵɵattribute": () => (/* binding */ ɵɵattribute), 50654/* harmony export */ "ɵɵattributeInterpolate1": () => (/* binding */ ɵɵattributeInterpolate1), 50655/* harmony export */ "ɵɵattributeInterpolate2": () => (/* binding */ ɵɵattributeInterpolate2), 50656/* harmony export */ "ɵɵattributeInterpolate3": () => (/* binding */ ɵɵattributeInterpolate3), 50657/* harmony export */ "ɵɵattributeInterpolate4": () => (/* binding */ ɵɵattributeInterpolate4), 50658/* harmony export */ "ɵɵattributeInterpolate5": () => (/* binding */ ɵɵattributeInterpolate5), 50659/* harmony export */ "ɵɵattributeInterpolate6": () => (/* binding */ ɵɵattributeInterpolate6), 50660/* harmony export */ "ɵɵattributeInterpolate7": () => (/* binding */ ɵɵattributeInterpolate7), 50661/* harmony export */ "ɵɵattributeInterpolate8": () => (/* binding */ ɵɵattributeInterpolate8), 50662/* harmony export */ "ɵɵattributeInterpolateV": () => (/* binding */ ɵɵattributeInterpolateV), 50663/* harmony export */ "ɵɵclassMap": () => (/* binding */ ɵɵclassMap), 50664/* harmony export */ "ɵɵclassMapInterpolate1": () => (/* binding */ ɵɵclassMapInterpolate1), 50665/* harmony export */ "ɵɵclassMapInterpolate2": () => (/* binding */ ɵɵclassMapInterpolate2), 50666/* harmony export */ "ɵɵclassMapInterpolate3": () => (/* binding */ ɵɵclassMapInterpolate3), 50667/* harmony export */ "ɵɵclassMapInterpolate4": () => (/* binding */ ɵɵclassMapInterpolate4), 50668/* harmony export */ "ɵɵclassMapInterpolate5": () => (/* binding */ ɵɵclassMapInterpolate5), 50669/* harmony export */ "ɵɵclassMapInterpolate6": () => (/* binding */ ɵɵclassMapInterpolate6), 50670/* harmony export */ "ɵɵclassMapInterpolate7": () => (/* binding */ ɵɵclassMapInterpolate7), 50671/* harmony export */ "ɵɵclassMapInterpolate8": () => (/* binding */ ɵɵclassMapInterpolate8), 50672/* harmony export */ "ɵɵclassMapInterpolateV": () => (/* binding */ ɵɵclassMapInterpolateV), 50673/* harmony export */ "ɵɵclassProp": () => (/* binding */ ɵɵclassProp), 50674/* harmony export */ "ɵɵcontentQuery": () => (/* binding */ ɵɵcontentQuery), 50675/* harmony export */ "ɵɵdefineComponent": () => (/* binding */ ɵɵdefineComponent), 50676/* harmony export */ "ɵɵdefineDirective": () => (/* binding */ ɵɵdefineDirective), 50677/* harmony export */ "ɵɵdefineInjectable": () => (/* binding */ ɵɵdefineInjectable), 50678/* harmony export */ "ɵɵdefineInjector": () => (/* binding */ ɵɵdefineInjector), 50679/* harmony export */ "ɵɵdefineNgModule": () => (/* binding */ ɵɵdefineNgModule), 50680/* harmony export */ "ɵɵdefinePipe": () => (/* binding */ ɵɵdefinePipe), 50681/* harmony export */ "ɵɵdirectiveInject": () => (/* binding */ ɵɵdirectiveInject), 50682/* harmony export */ "ɵɵdisableBindings": () => (/* binding */ ɵɵdisableBindings), 50683/* harmony export */ "ɵɵelement": () => (/* binding */ ɵɵelement), 50684/* harmony export */ "ɵɵelementContainer": () => (/* binding */ ɵɵelementContainer), 50685/* harmony export */ "ɵɵelementContainerEnd": () => (/* binding */ ɵɵelementContainerEnd), 50686/* harmony export */ "ɵɵelementContainerStart": () => (/* binding */ ɵɵelementContainerStart), 50687/* harmony export */ "ɵɵelementEnd": () => (/* binding */ ɵɵelementEnd), 50688/* harmony export */ "ɵɵelementStart": () => (/* binding */ ɵɵelementStart), 50689/* harmony export */ "ɵɵenableBindings": () => (/* binding */ ɵɵenableBindings), 50690/* harmony export */ "ɵɵgetCurrentView": () => (/* binding */ ɵɵgetCurrentView), 50691/* harmony export */ "ɵɵgetInheritedFactory": () => (/* binding */ ɵɵgetInheritedFactory), 50692/* harmony export */ "ɵɵhostProperty": () => (/* binding */ ɵɵhostProperty), 50693/* harmony export */ "ɵɵi18n": () => (/* binding */ ɵɵi18n), 50694/* harmony export */ "ɵɵi18nApply": () => (/* binding */ ɵɵi18nApply), 50695/* harmony export */ "ɵɵi18nAttributes": () => (/* binding */ ɵɵi18nAttributes), 50696/* harmony export */ "ɵɵi18nEnd": () => (/* binding */ ɵɵi18nEnd), 50697/* harmony export */ "ɵɵi18nExp": () => (/* binding */ ɵɵi18nExp), 50698/* harmony export */ "ɵɵi18nPostprocess": () => (/* binding */ ɵɵi18nPostprocess), 50699/* harmony export */ "ɵɵi18nStart": () => (/* binding */ ɵɵi18nStart), 50700/* harmony export */ "ɵɵinject": () => (/* binding */ ɵɵinject), 50701/* harmony export */ "ɵɵinjectAttribute": () => (/* binding */ ɵɵinjectAttribute), 50702/* harmony export */ "ɵɵinvalidFactory": () => (/* binding */ ɵɵinvalidFactory), 50703/* harmony export */ "ɵɵinvalidFactoryDep": () => (/* binding */ ɵɵinvalidFactoryDep), 50704/* harmony export */ "ɵɵlistener": () => (/* binding */ ɵɵlistener), 50705/* harmony export */ "ɵɵloadQuery": () => (/* binding */ ɵɵloadQuery), 50706/* harmony export */ "ɵɵnamespaceHTML": () => (/* binding */ ɵɵnamespaceHTML), 50707/* harmony export */ "ɵɵnamespaceMathML": () => (/* binding */ ɵɵnamespaceMathML), 50708/* harmony export */ "ɵɵnamespaceSVG": () => (/* binding */ ɵɵnamespaceSVG), 50709/* harmony export */ "ɵɵnextContext": () => (/* binding */ ɵɵnextContext), 50710/* harmony export */ "ɵɵngDeclareClassMetadata": () => (/* binding */ ɵɵngDeclareClassMetadata), 50711/* harmony export */ "ɵɵngDeclareComponent": () => (/* binding */ ɵɵngDeclareComponent), 50712/* harmony export */ "ɵɵngDeclareDirective": () => (/* binding */ ɵɵngDeclareDirective), 50713/* harmony export */ "ɵɵngDeclareFactory": () => (/* binding */ ɵɵngDeclareFactory), 50714/* harmony export */ "ɵɵngDeclareInjectable": () => (/* binding */ ɵɵngDeclareInjectable), 50715/* harmony export */ "ɵɵngDeclareInjector": () => (/* binding */ ɵɵngDeclareInjector), 50716/* harmony export */ "ɵɵngDeclareNgModule": () => (/* binding */ ɵɵngDeclareNgModule), 50717/* harmony export */ "ɵɵngDeclarePipe": () => (/* binding */ ɵɵngDeclarePipe), 50718/* harmony export */ "ɵɵpipe": () => (/* binding */ ɵɵpipe), 50719/* harmony export */ "ɵɵpipeBind1": () => (/* binding */ ɵɵpipeBind1), 50720/* harmony export */ "ɵɵpipeBind2": () => (/* binding */ ɵɵpipeBind2), 50721/* harmony export */ "ɵɵpipeBind3": () => (/* binding */ ɵɵpipeBind3), 50722/* harmony export */ "ɵɵpipeBind4": () => (/* binding */ ɵɵpipeBind4), 50723/* harmony export */ "ɵɵpipeBindV": () => (/* binding */ ɵɵpipeBindV), 50724/* harmony export */ "ɵɵprojection": () => (/* binding */ ɵɵprojection), 50725/* harmony export */ "ɵɵprojectionDef": () => (/* binding */ ɵɵprojectionDef), 50726/* harmony export */ "ɵɵproperty": () => (/* binding */ ɵɵproperty), 50727/* harmony export */ "ɵɵpropertyInterpolate": () => (/* binding */ ɵɵpropertyInterpolate),
50728/* harmony export */ "ɵɵpropertyInterpolate1": () => (/* binding */ ɵɵpropertyInterpolate1), 50729/* harmony export */ "ɵɵpropertyInterpolate2": () => (/* binding */ ɵɵpropertyInterpolate2), 50730/* harmony export */ "ɵɵpropertyInterpolate3": () => (/* binding */ ɵɵpropertyInterpolate3), 50731/* harmony export */ "ɵɵpropertyInterpolate4": () => (/* binding */ ɵɵpropertyInterpolate4), 50732/* harmony export */ "ɵɵpropertyInterpolate5": () => (/* binding */ ɵɵpropertyInterpolate5), 50733/* harmony export */ "ɵɵpropertyInterpolate6": () => (/* binding */ ɵɵpropertyInterpolate6), 50734/* harmony export */ "ɵɵpropertyInterpolate7": () => (/* binding */ ɵɵpropertyInterpolate7), 50735/* harmony export */ "ɵɵpropertyInterpolate8": () => (/* binding */ ɵɵpropertyInterpolate8), 50736/* harmony export */ "ɵɵpropertyInterpolateV": () => (/* binding */ ɵɵpropertyInterpolateV), 50737/* harmony export */ "ɵɵpureFunction0": () => (/* binding */ ɵɵpureFunction0), 50738/* harmony export */ "ɵɵpureFunction1": () => (/* binding */ ɵɵpureFunction1), 50739/* harmony export */ "ɵɵpureFunction2": () => (/* binding */ ɵɵpureFunction2), 50740/* harmony export */ "ɵɵpureFunction3": () => (/* binding */ ɵɵpureFunction3), 50741/* harmony export */ "ɵɵpureFunction4": () => (/* binding */ ɵɵpureFunction4), 50742/* harmony export */ "ɵɵpureFunction5": () => (/* binding */ ɵɵpureFunction5), 50743/* harmony export */ "ɵɵpureFunction6": () => (/* binding */ ɵɵpureFunction6), 50744/* harmony export */ "ɵɵpureFunction7": () => (/* binding */ ɵɵpureFunction7), 50745/* harmony export */ "ɵɵpureFunction8": () => (/* binding */ ɵɵpureFunction8), 50746/* harmony export */ "ɵɵpureFunctionV": () => (/* binding */ ɵɵpureFunctionV), 50747/* harmony export */ "ɵɵqueryRefresh": () => (/* binding */ ɵɵqueryRefresh), 50748/* harmony export */ "ɵɵreference": () => (/* binding */ ɵɵreference), 50749/* harmony export */ "ɵɵregisterNgModuleType": () => (/* binding */ registerNgModuleType), 50750/* harmony export */ "ɵɵresetView": () => (/* binding */ ɵɵresetView), 50751/* harmony export */ "ɵɵresolveBody": () => (/* binding */ ɵɵresolveBody), 50752/* harmony export */ "ɵɵresolveDocument": () => (/* binding */ ɵɵresolveDocument), 50753/* harmony export */ "ɵɵresolveWindow": () => (/* binding */ ɵɵresolveWindow), 50754/* harmony export */ "ɵɵrestoreView": () => (/* binding */ ɵɵrestoreView), 50755/* harmony export */ "ɵɵsanitizeHtml": () => (/* binding */ ɵɵsanitizeHtml),
50756/* harmony export */ "ɵɵsanitizeResourceUrl": () => (/* binding */ ɵɵsanitizeResourceUrl), 50757/* harmony export */ "ɵɵsanitizeScript": () => (/* binding */ ɵɵsanitizeScript), 50758/* harmony export */ "ɵɵsanitizeStyle": () => (/* binding */ ɵɵsanitizeStyle), 50759/* harmony export */ "ɵɵsanitizeUrl": () => (/* binding */ ɵɵsanitizeUrl), 50760/* harmony export */ "ɵɵsanitizeUrlOrResourceUrl": () => (/* binding */ ɵɵsanitizeUrlOrResourceUrl), 50761/* harmony export */ "ɵɵsetComponentScope": () => (/* binding */ ɵɵsetComponentScope), 50762/* harmony export */ "ɵɵsetNgModuleScope": () => (/* binding */ ɵɵsetNgModuleScope), 50763/* harmony export */ "ɵɵstyleMap": () => (/* binding */ ɵɵstyleMap), 50764/* harmony export */ "ɵɵstyleMapInterpolate1": () => (/* binding */ ɵɵstyleMapInterpolate1), 50765/* harmony export */ "ɵɵstyleMapInterpolate2": () => (/* binding */ ɵɵstyleMapInterpolate2), 50766/* harmony export */ "ɵɵstyleMapInterpolate3": () => (/* binding */ ɵɵstyleMapInterpolate3), 50767/* harmony export */ "ɵɵstyleMapInterpolate4": () => (/* binding */ ɵɵstyleMapInterpolate4), 50768/* harmony export */ "ɵɵstyleMapInterpolate5": () => (/* binding */ ɵɵstyleMapInterpolate5), 50769/* harmony export */ "ɵɵstyleMapInterpolate6": () => (/* binding */ ɵɵstyleMapInterpolate6), 50770/* harmony export */ "ɵɵstyleMapInterpolate7": () => (/* binding */ ɵɵstyleMapInterpolate7), 50771/* harmony export */ "ɵɵstyleMapInterpolate8": () => (/* binding */ ɵɵstyleMapInterpolate8), 50772/* harmony export */ "ɵɵstyleMapInterpolateV": () => (/* binding */ ɵɵstyleMapInterpolateV), 50773/* harmony export */ "ɵɵstyleProp": () => (/* binding */ ɵɵstyleProp), 50774/* harmony export */ "ɵɵstylePropInterpolate1": () => (/* binding */ ɵɵstylePropInterpolate1), 50775/* harmony export */ "ɵɵstylePropInterpolate2": () => (/* binding */ ɵɵstylePropInterpolate2), 50776/* harmony export */ "ɵɵstylePropInterpolate3": () => (/* binding */ ɵɵstylePropInterpolate3), 50777/* harmony export */ "ɵɵstylePropInterpolate4": () => (/* binding */ ɵɵstylePropInterpolate4), 50778/* harmony export */ "ɵɵstylePropInterpolate5": () => (/* binding */ ɵɵstylePropInterpolate5), 50779/* harmony export */ "ɵɵstylePropInterpolate6": () => (/* binding */ ɵɵstylePropInterpolate6), 50780/* harmony export */ "ɵɵstylePropInterpolate7": () => (/* binding */ ɵɵstylePropInterpolate7), 50781/* harmony export */ "ɵɵstylePropInterpolate8": () => (/* binding */ ɵɵstylePropInterpolate8), 50782/* harmony export */ "ɵɵstylePropInterpolateV": () => (/* binding */ ɵɵstylePropInterpolateV), 50783/* harmony export */ "ɵɵsyntheticHostListener": () => (/* binding */ ɵɵsyntheticHostListener), 50784/* harmony export */ "ɵɵsyntheticHostProperty": () => (/* binding */ ɵɵsyntheticHostProperty), 50785/* harmony export */ "ɵɵtemplate": () => (/* binding */ ɵɵtemplate), 50786/* harmony export */ "ɵɵtemplateRefExtractor": () => (/* binding */ ɵɵtemplateRefExtractor), 50787/* harmony export */ "ɵɵtext": () => (/* binding */ ɵɵtext), 50788/* harmony export */ "ɵɵtextInterpolate": () => (/* binding */ ɵɵtextInterpolate), 50789/* harmony export */ "ɵɵtextInterpolate1": () => (/* binding */ ɵɵtextInterpolate1), 50790/* harmony export */ "ɵɵtextInterpolate2": () => (/* binding */ ɵɵtextInterpolate2), 50791/* harmony export */ "ɵɵtextInterpolate3": () => (/* binding */ ɵɵtextInterpolate3), 50792/* harmony export */ "ɵɵtextInterpolate4": () => (/* binding */ ɵɵtextInterpolate4), 50793/* harmony export */ "ɵɵtextInterpolate5": () => (/* binding */ ɵɵtextInterpolate5), 50794/* harmony export */ "ɵɵtextInterpolate6": () => (/* binding */ ɵɵtextInterpolate6), 50795/* harmony export */ "ɵɵtextInterpolate7": () => (/* binding */ ɵɵtextInterpolate7), 50796/* harmony export */ "ɵɵtextInterpolate8": () => (/* binding */ ɵɵtextInterpolate8), 50797/* harmony export */ "ɵɵtextInterpolateV": () => (/* binding */ ɵɵtextInterpolateV), 50798/* harmony export */ "ɵɵtrustConstantHtml": () => (/* binding */ ɵɵtrustConstantHtml),
vendor: 5,395 bytes, lines 50799-50993
50799/* harmony export */ "ɵɵtrustConstantResourceUrl": () => (/* binding */ ɵɵtrustConstantResourceUrl), 50800/* harmony export */ "ɵɵviewQuery": () => (/* binding */ ɵɵviewQuery) 50801/* harmony export */ }); 50802/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! rxjs */ 2218); 50803/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs */ 2425); 50804/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 2378); 50805/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 8623); 50806/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs/operators */ 4514); 50807/** 50808 * @license Angular v14.2.10 50809 * (c) 2010-2022 Google LLC. https://angular.io/ 50810 * License: MIT 50811 */ 50812 50813 50814/** 50815 * @license 50816 * Copyright Google LLC All Rights Reserved. 50817 * 50818 * Use of this source code is governed by an MIT-style license that can be 50819 * found in the LICENSE file at https://angular.io/license 50820 */ 50821 50822function getClosureSafeProperty(objWithPropertyToExtract) { 50823 for (let key in objWithPropertyToExtract) { 50824 if (objWithPropertyToExtract[key] === getClosureSafeProperty) { 50825 return key; 50826 } 50827 } 50828 50829 throw Error('Could not find renamed property on target object.'); 50830} 50831/** 50832 * Sets properties on a target object from a source object, but only if 50833 * the property doesn't already exist on the target object. 50834 * @param target The target to set properties on 50835 * @param source The source of the property keys and values to set 50836 */ 50837 50838 50839function fillProperties(target, source) { 50840 for (const key in source) { 50841 if (source.hasOwnProperty(key) && !target.hasOwnProperty(key)) { 50842 target[key] = source[key]; 50843 } 50844 } 50845} 50846/** 50847 * @license 50848 * Copyright Google LLC All Rights Reserved. 50849 * 50850 * Use of this source code is governed by an MIT-style license that can be 50851 * found in the LICENSE file at https://angular.io/license 50852 */ 50853 50854 50855function stringify(token) { 50856 if (typeof token === 'string') { 50857 return token; 50858 } 50859 50860 if (Array.isArray(token)) { 50861 return '[' + token.map(stringify).join(', ') + ']'; 50862 } 50863 50864 if (token == null) { 50865 return '' + token; 50866 } 50867 50868 if (token.overriddenName) { 50869 return `${token.overriddenName}`; 50870 } 50871 50872 if (token.name) { 50873 return `${token.name}`; 50874 } 50875 50876 const res = token.toString(); 50877 50878 if (res == null) { 50879 return '' + res; 50880 } 50881 50882 const newLineIndex = res.indexOf('\n'); 50883 return newLineIndex === -1 ? res : res.substring(0, newLineIndex); 50884} 50885/** 50886 * Concatenates two strings with separator, allocating new strings only when necessary. 50887 * 50888 * @param before before string. 50889 * @param separator separator string. 50890 * @param after after string. 50891 * @returns concatenated string. 50892 */ 50893 50894 50895function concatStringsWithSpace(before, after) { 50896 return before == null || before === '' ? after === null ? '' : after : after == null || after === '' ? before : before + ' ' + after; 50897} 50898/** 50899 * @license 50900 * Copyright Google LLC All Rights Reserved. 50901 * 50902 * Use of this source code is governed by an MIT-style license that can be 50903 * found in the LICENSE file at https://angular.io/license 50904 */ 50905 50906 50907const __forward_ref__ = getClosureSafeProperty({ 50908 __forward_ref__: getClosureSafeProperty 50909}); 50910/** 50911 * Allows to refer to references which are not yet defined. 50912 * 50913 * For instance, `forwardRef` is used when the `token` which we need to refer to for the purposes of 50914 * DI is declared, but not yet defined. It is also used when the `token` which we use when creating 50915 * a query is not yet defined. 50916 * 50917 * @usageNotes 50918 * ### Example 50919 * {@example core/di/ts/forward_ref/forward_ref_spec.ts region='forward_ref'} 50920 * @publicApi 50921 */ 50922 50923 50924function forwardRef(forwardRefFn) { 50925 forwardRefFn.__forward_ref__ = forwardRef; 50926 50927 forwardRefFn.toString = function () { 50928 return stringify(this()); 50929 }; 50930 50931 return forwardRefFn; 50932} 50933/** 50934 * Lazily retrieves the reference value from a forwardRef. 50935 * 50936 * Acts as the identity function when given a non-forward-ref value. 50937 * 50938 * @usageNotes 50939 * ### Example 50940 * 50941 * {@example core/di/ts/forward_ref/forward_ref_spec.ts region='resolve_forward_ref'} 50942 * 50943 * @see `forwardRef` 50944 * @publicApi 50945 */ 50946 50947 50948function resolveForwardRef(type) { 50949 return isForwardRef(type) ? type() : type; 50950} 50951/** Checks whether a function is wrapped by a `forwardRef`. */ 50952 50953 50954function isForwardRef(fn) { 50955 return typeof fn === 'function' && fn.hasOwnProperty(__forward_ref__) && fn.__forward_ref__ === forwardRef; 50956} 50957/** 50958 * @license 50959 * Copyright Google LLC All Rights Reserved. 50960 * 50961 * Use of this source code is governed by an MIT-style license that can be 50962 * found in the LICENSE file at https://angular.io/license 50963 */ 50964 50965/** 50966 * Base URL for the error details page. 50967 * 50968 * Keep the files below in full sync: 50969 * - packages/compiler-cli/src/ngtsc/diagnostics/src/error_details_base_url.ts 50970 * - packages/core/src/error_details_base_url.ts 50971 */ 50972 50973 50974const ERROR_DETAILS_PAGE_BASE_URL = 'https://angular.io/errors'; 50975/** 50976 * @license 50977 * Copyright Google LLC All Rights Reserved. 50978 * 50979 * Use of this source code is governed by an MIT-style license that can be 50980 * found in the LICENSE file at https://angular.io/license 50981 */ 50982 50983/** 50984 * Class that represents a runtime error. 50985 * Formats and outputs the error message in a consistent way. 50986 * 50987 * Example: 50988 * ``` 50989 * throw new RuntimeError( 50990 * RuntimeErrorCode.INJECTOR_ALREADY_DESTROYED, 50991 * ngDevMode && 'Injector has already been destroyed.'); 50992 * ``` 50993 *
50994 * Note: the `message` argument contains a descriptive error message as a string in development 50995 * mode (when the `ngDevMode` is defined). In production mode (after tree-shaking pass), the 50996 * `message` argument becomes `false`, thus we account for it in the typings and the runtime logic. 50997 */ 50998 50999class RuntimeError extends Error { 51000 constructor(code, message) { 51001 super(formatRuntimeError(code, message)); 51002 this.code = code; 51003 } 51004 51005} 51006/** 51007 * Called to format a runtime error. 51008 * See additional info on the `message` argument type in the `RuntimeError` class description. 51009 */ 51010 51011 51012function formatRuntimeError(code, message) { 51013 // Error code might be a negative number, which is a special marker that instructs the logic to 51014 // generate a link to the error details page on angular.io. 51015 const fullCode = `NG0${Math.abs(code)}`; 51016 let errorMessage = `${fullCode}${message ? ': ' + message.trim() : ''}`; 51017 51018 if (ngDevMode && code < 0) { 51019 const addPeriodSeparator = !errorMessage.match(/[.,;!?]$/); 51020 const separator = addPeriodSeparator ? '.' : ''; 51021 errorMessage = `${errorMessage}${separator} Find more at ${ERROR_DETAILS_PAGE_BASE_URL}/${fullCode}`; 51022 } 51023 51024 return errorMessage; 51025} 51026/** 51027 * @license 51028 * Copyright Google LLC All Rights Reserved. 51029 * 51030 * Use of this source code is governed by an MIT-style license that can be 51031 * found in the LICENSE file at https://angular.io/license 51032 */ 51033 51034/** 51035 * Used for stringify render output in Ivy. 51036 * Important! This function is very performance-sensitive and we should 51037 * be extra careful not to introduce megamorphic reads in it. 51038 * Check `core/test/render3/perf/render_stringify` for benchmarks and alternate implementations. 51039 */ 51040 51041
vendor: 6,915 bytes, lines 51042-51248
51042function renderStringify(value) { 51043 if (typeof value === 'string') return value; 51044 if (value == null) return ''; // Use `String` so that it invokes the `toString` method of the value. Note that this 51045 // appears to be faster than calling `value.toString` (see `render_stringify` benchmark). 51046 51047 return String(value); 51048} 51049/** 51050 * Used to stringify a value so that it can be displayed in an error message. 51051 * Important! This function contains a megamorphic read and should only be 51052 * used for error messages. 51053 */ 51054 51055 51056function stringifyForError(value) { 51057 if (typeof value === 'function') return value.name || value.toString(); 51058 51059 if (typeof value === 'object' && value != null && typeof value.type === 'function') { 51060 return value.type.name || value.type.toString(); 51061 } 51062 51063 return renderStringify(value); 51064} 51065/** 51066 * @license 51067 * Copyright Google LLC All Rights Reserved. 51068 * 51069 * Use of this source code is governed by an MIT-style license that can be 51070 * found in the LICENSE file at https://angular.io/license 51071 */ 51072 51073/** Called when directives inject each other (creating a circular dependency) */ 51074 51075 51076function throwCyclicDependencyError(token, path) { 51077 const depPath = path ? `. Dependency path: ${path.join(' > ')} > ${token}` : ''; 51078 throw new RuntimeError(-200 51079 /* RuntimeErrorCode.CYCLIC_DI_DEPENDENCY */ 51080 , `Circular dependency in DI detected for ${token}${depPath}`); 51081} 51082 51083function throwMixedMultiProviderError() { 51084 throw new Error(`Cannot mix multi providers and regular providers`); 51085} 51086 51087function throwInvalidProviderError(ngModuleType, providers, provider) { 51088 if (ngModuleType && providers) { 51089 const providerDetail = providers.map(v => v == provider ? '?' + provider + '?' : '...'); 51090 throw new Error(`Invalid provider for the NgModule '${stringify(ngModuleType)}' - only instances of Provider and Type are allowed, got: [${providerDetail.join(', ')}]`); 51091 } else if (provider.ɵproviders) { 51092 throw new RuntimeError(207 51093 /* RuntimeErrorCode.PROVIDER_IN_WRONG_CONTEXT */ 51094 , `Invalid providers from 'importProvidersFrom' present in a non-environment injector. 'importProvidersFrom' can't be used for component providers.`); 51095 } else { 51096 throw new Error('Invalid provider'); 51097 } 51098} 51099/** Throws an error when a token is not found in DI. */ 51100 51101 51102function throwProviderNotFoundError(token, injectorName) { 51103 const injectorDetails = injectorName ? ` in ${injectorName}` : ''; 51104 throw new RuntimeError(-201 51105 /* RuntimeErrorCode.PROVIDER_NOT_FOUND */ 51106 , ngDevMode && `No provider for ${stringifyForError(token)} found${injectorDetails}`); 51107} 51108/** 51109 * @license 51110 * Copyright Google LLC All Rights Reserved. 51111 * 51112 * Use of this source code is governed by an MIT-style license that can be 51113 * found in the LICENSE file at https://angular.io/license 51114 */ 51115 51116 51117function assertNumber(actual, msg) { 51118 if (!(typeof actual === 'number')) { 51119 throwError(msg, typeof actual, 'number', '==='); 51120 } 51121} 51122 51123function assertNumberInRange(actual, minInclusive, maxInclusive) { 51124 assertNumber(actual, 'Expected a number'); 51125 assertLessThanOrEqual(actual, maxInclusive, 'Expected number to be less than or equal to'); 51126 assertGreaterThanOrEqual(actual, minInclusive, 'Expected number to be greater than or equal to'); 51127} 51128 51129function assertString(actual, msg) { 51130 if (!(typeof actual === 'string')) { 51131 throwError(msg, actual === null ? 'null' : typeof actual, 'string', '==='); 51132 } 51133} 51134 51135function assertFunction(actual, msg) { 51136 if (!(typeof actual === 'function')) { 51137 throwError(msg, actual === null ? 'null' : typeof actual, 'function', '==='); 51138 } 51139} 51140 51141function assertEqual(actual, expected, msg) { 51142 if (!(actual == expected)) { 51143 throwError(msg, actual, expected, '=='); 51144 } 51145} 51146 51147function assertNotEqual(actual, expected, msg) { 51148 if (!(actual != expected)) { 51149 throwError(msg, actual, expected, '!='); 51150 } 51151} 51152 51153function assertSame(actual, expected, msg) { 51154 if (!(actual === expected)) { 51155 throwError(msg, actual, expected, '==='); 51156 } 51157} 51158 51159function assertNotSame(actual, expected, msg) { 51160 if (!(actual !== expected)) { 51161 throwError(msg, actual, expected, '!=='); 51162 } 51163} 51164 51165function assertLessThan(actual, expected, msg) { 51166 if (!(actual < expected)) { 51167 throwError(msg, actual, expected, '<'); 51168 } 51169} 51170 51171function assertLessThanOrEqual(actual, expected, msg) { 51172 if (!(actual <= expected)) { 51173 throwError(msg, actual, expected, '<='); 51174 } 51175} 51176 51177function assertGreaterThan(actual, expected, msg) { 51178 if (!(actual > expected)) { 51179 throwError(msg, actual, expected, '>'); 51180 } 51181} 51182 51183function assertGreaterThanOrEqual(actual, expected, msg) { 51184 if (!(actual >= expected)) { 51185 throwError(msg, actual, expected, '>='); 51186 } 51187} 51188 51189function assertNotDefined(actual, msg) { 51190 if (actual != null) { 51191 throwError(msg, actual, null, '=='); 51192 } 51193} 51194 51195function assertDefined(actual, msg) { 51196 if (actual == null) { 51197 throwError(msg, actual, null, '!='); 51198 } 51199} 51200 51201function throwError(msg, actual, expected, comparison) { 51202 throw new Error(`ASSERTION ERROR: ${msg}` + (comparison == null ? '' : ` [Expected=> ${expected} ${comparison} ${actual} <=Actual]`)); 51203} 51204 51205function assertDomNode(node) { 51206 // If we're in a worker, `Node` will not be defined. 51207 if (!(typeof Node !== 'undefined' && node instanceof Node) && !(typeof node === 'object' && node != null && node.constructor.name === 'WebWorkerRenderNode')) { 51208 throwError(`The provided value must be an instance of a DOM Node but got ${stringify(node)}`); 51209 } 51210} 51211 51212function assertIndexInRange(arr, index) { 51213 assertDefined(arr, 'Array must be defined.'); 51214 const maxLen = arr.length; 51215 51216 if (index < 0 || index >= maxLen) { 51217 throwError(`Index expected to be less than ${maxLen} but got ${index}`); 51218 } 51219} 51220 51221function assertOneOf(value, ...validValues) { 51222 if (validValues.indexOf(value) !== -1) return true; 51223 throwError(`Expected value to be one of ${JSON.stringify(validValues)} but was ${JSON.stringify(value)}.`); 51224} 51225/** 51226 * @license 51227 * Copyright Google LLC All Rights Reserved. 51228 * 51229 * Use of this source code is governed by an MIT-style license that can be 51230 * found in the LICENSE file at https://angular.io/license 51231 */ 51232 51233/** 51234 * Construct an injectable definition which defines how a token will be constructed by the DI 51235 * system, and in which injectors (if any) it will be available. 51236 * 51237 * This should be assigned to a static `ɵprov` field on a type, which will then be an 51238 * `InjectableType`. 51239 * 51240 * Options: 51241 * * `providedIn` determines which injectors will include the injectable, by either associating it 51242 * with an `@NgModule` or other `InjectorType`, or by specifying that this injectable should be 51243 * provided in the `'root'` injector, which will be the application-level injector in most apps. 51244 * * `factory` gives the zero argument function which will create an instance of the injectable. 51245 * The factory can call `inject` to access the `Injector` and request injection of dependencies. 51246 * 51247 * @codeGenApi 51248 * @publicApi This instruction has been emitted by ViewEngine for some time and is deployed to
51248npm. 51249 */ 51250 51251 51252function ɵɵdefineInjectable(opts) { 51253 return { 51254 token: opts.token, 51255 providedIn: opts.providedIn || null, 51256 factory: opts.factory, 51257 value: undefined 51258 }; 51259} 51260/** 51261 * @deprecated in v8, delete after v10. This API should be used only by generated code, and that 51262 * code should now use ɵɵdefineInjectable instead. 51263 * @publicApi 51264 */ 51265 51266 51267const defineInjectable = ɵɵdefineInjectable; 51268/** 51269 * Construct an `InjectorDef` which configures an injector. 51270 * 51271 * This should be assigned to a static injector def (`ɵinj`) field on a type, which will then be an 51272 * `InjectorType`. 51273 * 51274 * Options: 51275 * 51276 * * `providers`: an optional array of providers to add to the injector. Each provider must 51277 * either have a factory or point to a type which has a `ɵprov` static property (the 51278 * type must be an `InjectableType`). 51279 * * `imports`: an optional array of imports of other `InjectorType`s or `InjectorTypeWithModule`s 51280 * whose providers will also be added to the injector. Locally provided types will override 51281 * providers from imports. 51282 * 51283 * @codeGenApi 51284 */ 51285 51286function ɵɵdefineInjector(options) { 51287 return { 51288 providers: options.providers || [], 51289 imports: options.imports || [] 51290 }; 51291} 51292/** 51293 * Read the injectable def (`ɵprov`) for `type` in a way which is immune to accidentally reading 51294 * inherited value. 51295 * 51296 * @param type A type which may have its own (non-inherited) `ɵprov`. 51297 */ 51298 51299 51300function getInjectableDef(type) { 51301 return getOwnDefinition(type, NG_PROV_DEF) || getOwnDefinition(type, NG_INJECTABLE_DEF); 51302} 51303 51304function isInjectable(type) { 51305 return getInjectableDef(type) !== null; 51306} 51307/** 51308 * Return definition only if it is defined directly on `type` and is not inherited from a base 51309 * class of `type`. 51310 */ 51311 51312 51313function getOwnDefinition(type, field) { 51314 return type.hasOwnProperty(field) ? type[field] : null; 51315} 51316/** 51317 * Read the injectable def (`ɵprov`) for `type` or read the `ɵprov` from one of its ancestors. 51318 * 51319 * @param type A type which may have `ɵprov`, via inheritance. 51320 * 51321 * @deprecated Will be removed in a future version of Angular, where an error will occur in the 51322 * scenario if we find the `ɵprov` on an ancestor only. 51323 */ 51324 51325 51326function getInheritedInjectableDef(type) { 51327 const def = type && (type[NG_PROV_DEF] || type[NG_INJECTABLE_DEF]); 51328 51329 if (def) { 51330 const typeName = getTypeName(type); // TODO(FW-1307): Re-add ngDevMode when closure can handle it 51331 // ngDevMode && 51332 51333 console.warn(`DEPRECATED: DI is instantiating a token "${typeName}" that inherits its @Injectable decorator but does not provide one itself.\n` + `This will become an error in a future version of Angular. Please add @Injectable() to the "${typeName}" class.`); 51334 return def; 51335 } else { 51336 return null; 51337 } 51338} 51339/** Gets the name of a type, accounting for some cross-browser differences. */ 51340 51341 51342function getTypeName(type) { 51343 // `Function.prototype.name` behaves differently between IE and other browsers. In most browsers 51344 // it'll always return the name of the function itself, no matter how many other functions it 51345 // inherits from. On IE the function doesn't have its own `name` property, but it takes it from 51346 // the lowest level in the prototype chain. E.g. if we have `class Foo extends Parent` most 51347 // browsers will evaluate `Foo.name` to `Foo` while IE will return `Parent`. We work around 51348 // the issue by converting the function to a string and parsing its name out that way via a regex. 51349 if (type.hasOwnProperty('name')) { 51350 return type.name; 51351 } 51352 51353 const match = ('' + type).match(/^function\s*([^\s(]+)/); 51354 return match === null ? '' : match[1]; 51355} 51356/** 51357 * Read the injector def type in a way which is immune to accidentally reading inherited value. 51358 * 51359 * @param type type which may have an injector def (`ɵinj`) 51360 */ 51361 51362 51363function getInjectorDef(type) { 51364 return type && (type.hasOwnProperty(NG_INJ_DEF) || type.hasOwnProperty(NG_INJECTOR_DEF)) ? type[NG_INJ_DEF] : null; 51365} 51366 51367const NG_PROV_DEF = getClosureSafeProperty({ 51368 ɵprov: getClosureSafeProperty 51369}); 51370const NG_INJ_DEF = getClosureSafeProperty({ 51371 ɵinj: getClosureSafeProperty 51372}); // We need to keep these around so we can read off old defs if new defs are unavailable 51373 51374const NG_INJECTABLE_DEF = getClosureSafeProperty({ 51375 ngInjectableDef: getClosureSafeProperty 51376}); 51377const NG_INJECTOR_DEF = getClosureSafeProperty({ 51378 ngInjectorDef: getClosureSafeProperty 51379}); 51380/** 51381 * @license 51382 * Copyright Google LLC All Rights Reserved. 51383 * 51384 * Use of this source code is governed by an MIT-style license that can be 51385 * found in the LICENSE file at https://angular.io/license 51386 */ 51387 51388/** 51389 * Injection flags for DI. 51390 * 51391 * @publicApi 51392 * @deprecated use an options object for `inject` instead. 51393 */ 51394 51395var InjectFlags; 51396 51397(function (InjectFlags) { 51398 // TODO(alxhub): make this 'const' (and remove `InternalInjectFlags` enum) when ngc no longer 51399 // writes exports of it into ngfactory files. 51400
51401 /** Check self and check parent injector if needed */ 51402 InjectFlags[InjectFlags["Default"] = 0] = "Default"; 51403 /** 51404 * Specifies that an injector should retrieve a dependency from any injector until reaching the 51405 * host element of the current component. (Only used with Element Injector) 51406 */ 51407 51408 InjectFlags[InjectFlags["Host"] = 1] = "Host"; 51409 /** Don't ascend to ancestors of the node requesting injection. */ 51410 51411 InjectFlags[InjectFlags["Self"] = 2] = "Self"; 51412 /** Skip the node that is requesting injection. */ 51413 51414 InjectFlags[InjectFlags["SkipSelf"] = 4] = "SkipSelf"; 51415 /** Inject `defaultValue` instead if token not found. */ 51416 51417 InjectFlags[InjectFlags["Optional"] = 8] = "Optional"; 51418})(InjectFlags || (InjectFlags = {})); 51419/** 51420 * @license 51421 * Copyright Google LLC All Rights Reserved. 51422 * 51423 * Use of this source code is governed by an MIT-style license that can be 51424 * found in the LICENSE file at https://angular.io/license 51425 */ 51426 51427/** 51428 * Current implementation of inject. 51429 * 51430 * By default, it is `injectInjectorOnly`, which makes it `Injector`-only aware. It can be changed 51431 * to `directiveInject`, which brings in the `NodeInjector` system of ivy. It is designed this 51432 * way for two reasons: 51433 * 1. `Injector` should not depend on ivy logic. 51434 * 2. To maintain tree shake-ability we don't want to bring in unnecessary code. 51435 */ 51436 51437 51438let _injectImplementation; 51439 51440function getInjectImplementation() { 51441 return _injectImplementation; 51442} 51443/** 51444 * Sets the current inject implementation. 51445 */ 51446 51447 51448function setInjectImplementation(impl) { 51449 const previous = _injectImplementation; 51450 _injectImplementation = impl; 51451 return previous; 51452} 51453/** 51454 * Injects `root` tokens in limp mode. 51455 * 51456 * If no injector exists, we can still inject tree-shakable providers which have `providedIn` set to 51457 * `"root"`. This is known as the limp mode injection. In such case the value is stored in the 51458 * injectable definition. 51459 */ 51460 51461 51462function injectRootLimpMode(token, notFoundValue, flags) { 51463 const injectableDef = getInjectableDef(token); 51464 51465 if (injectableDef && injectableDef.providedIn == 'root') { 51466 return injectableDef.value === undefined ? injectableDef.value = injectableDef.factory() : injectableDef.value; 51467 } 51468 51469 if (flags & InjectFlags.Optional) return null; 51470 if (notFoundValue !== undefined) return notFoundValue; 51471 throwProviderNotFoundError(stringify(token), 'Injector'); 51472} 51473/** 51474 * Assert that `_injectImplementation` is not `fn`. 51475 * 51476 * This is useful, to prevent infinite recursion. 51477 * 51478 * @param fn Function which it should not equal to 51479 */ 51480 51481 51482function assertInjectImplementationNotEqual(fn) { 51483 ngDevMode && assertNotEqual(_injectImplementation, fn, 'Calling ɵɵinject would cause infinite recursion'); 51484} 51485/** 51486 * @license 51487 * Copyright Google LLC All Rights Reserved. 51488 * 51489 * Use of this source code is governed by an MIT-style license that can be 51490 * found in the LICENSE file at https://angular.io/license 51491 */ 51492 51493/** 51494 * Convince closure compiler that the wrapped function has no side-effects. 51495 * 51496 * Closure compiler always assumes that `toString` has no side-effects. We use this quirk to 51497 * allow us to execute a function but have closure compiler mark the call as no-side-effects. 51498 * It is important that the return value for the `noSideEffects` function be assigned 51499 * to something which is retained otherwise the call to `noSideEffects` will be removed by closure 51500 * compiler. 51501 */ 51502 51503 51504function noSideEffects(fn) { 51505 return { 51506 toString: fn 51507 }.toString(); 51508} 51509/** 51510 * @license 51511 * Copyright Google LLC All Rights Reserved. 51512 * 51513 * Use of this source code is governed by an MIT-style license that can be 51514 * found in the LICENSE file at https://angular.io/license 51515 */ 51516 51517/** 51518 * The strategy that the default change detector uses to detect changes. 51519 * When set, takes effect the next time change detection is triggered. 51520 * 51521 * @see {@link ChangeDetectorRef#usage-notes Change detection usage} 51522 * 51523 * @publicApi 51524 */ 51525 51526 51527var ChangeDetectionStrategy; 51528 51529(function (ChangeDetectionStrategy) { 51530 /** 51531 * Use the `CheckOnce` strategy, meaning that automatic change detection is deactivated 51532 * until reactivated by setting the strategy to `Default` (`CheckAlways`). 51533 * Change detection can still be explicitly invoked. 51534 * This strategy applies to all child directives and cannot be overridden. 51535 */ 51536 ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush"; 51537 /** 51538 * Use the default `CheckAlways` strategy, in which change detection is automatic until 51539 * explicitly deactivated. 51540 */ 51541 51542 ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default"; 51543})(ChangeDetectionStrategy || (ChangeDetectionStrategy = {})); 51544/** 51545 * Defines the possible states of the default change detector. 51546 * @see `ChangeDetectorRef` 51547 */ 51548 51549 51550var ChangeDetectorStatus; 51551 51552(function (ChangeDetectorStatus) { 51553 /** 51554 * A state in which, after calling `detectChanges()`, the change detector 51555 * state becomes `Checked`, and must be explicitly invoked or reactivated. 51556 */ 51557 ChangeDetectorStatus[ChangeDetectorStatus["CheckOnce"] = 0] = "CheckOnce"; 51558 /** 51559 * A state in which change detection is skipped until the change detector mode 51560 * becomes `CheckOnce`. 51561 */ 51562 51563 ChangeDetectorStatus[ChangeDetectorStatus["Checked"] = 1] = "Checked"; 51564 /** 51565 * A state in which change detection continues automatically until explicitly 51566 * deactivated. 51567 */ 51568 51569 ChangeDetectorStatus[ChangeDetectorStatus["CheckAlways"] = 2] = "CheckAlways"; 51570 /** 51571 * A state in which a change detector sub tree is not a part of the main tree and 51572 * should be skipped. 51573 */ 51574 51575 ChangeDetectorStatus[ChangeDetectorStatus["Detached"] = 3] = "Detached"; 51576 /** 51577 * Indicates that the change detector encountered an error checking a binding 51578 * or calling a directive lifecycle method and is now in an inconsistent state. Change 51579 * detectors in this state do not detect changes. 51580 */ 51581
51582 ChangeDetectorStatus[ChangeDetectorStatus["Errored"] = 4] = "Errored"; 51583 /** 51584 * Indicates that the change detector has been destroyed. 51585 */ 51586 51587 ChangeDetectorStatus[ChangeDetectorStatus["Destroyed"] = 5] = "Destroyed"; 51588})(ChangeDetectorStatus || (ChangeDetectorStatus = {})); 51589/** 51590 * Reports whether a given strategy is currently the default for change detection. 51591 * @param changeDetectionStrategy The strategy to check. 51592 * @returns True if the given strategy is the current default, false otherwise. 51593 * @see `ChangeDetectorStatus` 51594 * @see `ChangeDetectorRef` 51595 */ 51596 51597 51598function isDefaultChangeDetectionStrategy(changeDetectionStrategy) { 51599 return changeDetectionStrategy == null || changeDetectionStrategy === ChangeDetectionStrategy.Default; 51600} 51601/** 51602 * @license 51603 * Copyright Google LLC All Rights Reserved. 51604 * 51605 * Use of this source code is governed by an MIT-style license that can be 51606 * found in the LICENSE file at https://angular.io/license 51607 */ 51608 51609/** 51610 * Defines the CSS styles encapsulation policies for the {@link Component} decorator's 51611 * `encapsulation` option. 51612 * 51613 * See {@link Component#encapsulation encapsulation}. 51614 * 51615 * @usageNotes 51616 * ### Example 51617 * 51618 * {@example core/ts/metadata/encapsulation.ts region='longform'} 51619 * 51620 * @publicApi 51621 */ 51622 51623 51624var ViewEncapsulation$1; 51625 51626(function (ViewEncapsulation) { 51627 // TODO: consider making `ViewEncapsulation` a `const enum` instead. See 51628 // https://github.com/angular/angular/issues/44119 for additional information. 51629 51630 /** 51631 * Emulates a native Shadow DOM encapsulation behavior by adding a specific attribute to the 51632 * component's host element and applying the same attribute to all the CSS selectors provided 51633 * via {@link Component#styles styles} or {@link Component#styleUrls styleUrls}. 51634 * 51635 * This is the default option. 51636 */ 51637 ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated"; // Historically the 1 value was for `Native` encapsulation which has been removed as of v11. 51638 51639 /** 51640 * Doesn't provide any sort of CSS style encapsulation, meaning that all the styles provided 51641 * via {@link Component#styles styles} or {@link Component#styleUrls styleUrls} are applicable 51642 * to any HTML element of the application regardless of their host Component. 51643 */ 51644 51645 ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None"; 51646 /** 51647 * Uses the browser's native Shadow DOM API to encapsulate CSS styles, meaning that it creates 51648 * a ShadowRoot for the component's host element which is then used to encapsulate 51649 * all the Component's styling. 51650 */ 51651 51652 ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom"; 51653})(ViewEncapsulation$1 || (ViewEncapsulation$1 = {})); 51654/** 51655 * @license 51656 * Copyright Google LLC All Rights Reserved. 51657 * 51658 * Use of this source code is governed by an MIT-style license that can be 51659 * found in the LICENSE file at https://angular.io/license 51660 */ 51661// Always use __globalThis if available, which is the spec-defined global variable across all 51662// environments, then fallback to __global first, because in Node tests both __global and 51663// __window may be defined and _global should be __global in that case. Note: Typeof/Instanceof 51664// checks are considered side-effects in Terser. We explicitly mark this as side-effect free: 51665// https://github.com/terser/terser/issues/250. 51666 51667 51668const _global = /* @__PURE__ */(() => typeof globalThis !== 'undefined' && globalThis || typeof global !== 'undefined' && global || typeof window !== 'undefined' && window || typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope && self)(); 51669/** 51670 * @license 51671 * Copyright Google LLC All Rights Reserved. 51672 * 51673 * Use of this source code is governed by an MIT-style license that can be 51674 * found in the LICENSE file at https://angular.io/license 51675 */ 51676 51677 51678function ngDevModeResetPerfCounters() { 51679 const locationString = typeof location !== 'undefined' ? location.toString() : ''; 51680 const newCounters = { 51681 namedConstructors: locationString.indexOf('ngDevMode=namedConstructors') != -1, 51682 firstCreatePass: 0, 51683 tNode: 0, 51684 tView: 0, 51685 rendererCreateTextNode: 0, 51686 rendererSetText: 0, 51687 rendererCreateElement: 0, 51688 rendererAddEventListener: 0, 51689 rendererSetAttribute: 0, 51690 rendererRemoveAttribute: 0, 51691 rendererSetProperty: 0, 51692 rendererSetClassName: 0, 51693 rendererAddClass: 0, 51694 rendererRemoveClass: 0, 51695 rendererSetStyle: 0, 51696 rendererRemoveStyle: 0, 51697 rendererDestroy: 0, 51698 rendererDestroyNode: 0, 51699 rendererMoveNode: 0, 51700 rendererRemoveNode: 0, 51701 rendererAppendChild: 0, 51702 rendererInsertBefore: 0, 51703 rendererCreateComment: 0 51704 }; // Make sure to refer to ngDevMode as ['ngDevMode'] for closure. 51705 51706 const allowNgDevModeTrue = locationString.indexOf('ngDevMode=false') === -1; 51707 _global['ngDevMode'] = allowNgDevModeTrue && newCounters; 51708 return newCounters; 51709} 51710/** 51711 * This function checks to see if the `ngDevMode` has been set. If yes, 51712 * then we honor it, otherwise we default to dev mode with additional checks. 51713 * 51714 * The idea is that unless we are doing production build where we explicitly 51715 * set `ngDevMode == false` we should be helping the developer by providing 51716 * as much early warning and errors as possible. 51717 * 51718 * `ɵɵdefineComponent` is guaranteed to have been called before any component template functions 51719 * (and thus Ivy instructions), so a single initialization there is sufficient to ensure ngDevMode 51720 * is defined for the entire instruction set. 51721 * 51722 * When checking `ngDevMode` on toplevel, always init it before referencing it 51723 * (e.g. `((typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode())`), otherwise you can 51724 * get a `ReferenceError` like in https://github.com/angular/angular/issues/31595. 51725 * 51726 * Details on possible values for `ngDevMode` can be found on its docstring. 51727 * 51728 * NOTE: 51729 * - changes to the `ngDevMode` name must be synced with `compiler-cli/src/tooling.ts`. 51730 */ 51731 51732 51733function initNgDevMode() { 51734 // The below checks are to ensure that calling `initNgDevMode` multiple times does not 51735 // reset the counters. 51736 // If the `ngDevMode` is not an object, then it means we have not created the perf counters 51737 // yet. 51738 if (typeof ngDevMode === 'undefined' || ngDevMode) { 51739 if (typeof ngDevMode !== 'object') { 51740 ngDevModeResetPerfCounters(); 51741 } 51742 51743 return typeof ngDevMode !== 'undefined' && !!ngDevMode; 51744 } 51745 51746 return false;
51747} 51748/** 51749 * @license 51750 * Copyright Google LLC All Rights Reserved. 51751 * 51752 * Use of this source code is governed by an MIT-style license that can be 51753 * found in the LICENSE file at https://angular.io/license 51754 */ 51755 51756/** 51757 * This file contains reuseable "empty" symbols that can be used as default return values 51758 * in different parts of the rendering code. Because the same symbols are returned, this 51759 * allows for identity checks against these values to be consistently used by the framework 51760 * code. 51761 */ 51762 51763 51764const EMPTY_OBJ = {}; 51765const EMPTY_ARRAY = []; // freezing the values prevents any code from accidentally inserting new values in 51766 51767if ((typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode()) { 51768 // These property accesses can be ignored because ngDevMode will be set to false 51769 // when optimizing code and the whole if statement will be dropped. 51770 // tslint:disable-next-line:no-toplevel-property-access 51771 Object.freeze(EMPTY_OBJ); // tslint:disable-next-line:no-toplevel-property-access 51772 51773 Object.freeze(EMPTY_ARRAY); 51774} 51775/** 51776 * @license 51777 * Copyright Google LLC All Rights Reserved. 51778 * 51779 * Use of this source code is governed by an MIT-style license that can be 51780 * found in the LICENSE file at https://angular.io/license 51781 */ 51782 51783 51784const NG_COMP_DEF = getClosureSafeProperty({ 51785 ɵcmp: getClosureSafeProperty 51786}); 51787const NG_DIR_DEF = getClosureSafeProperty({ 51788 ɵdir: getClosureSafeProperty 51789}); 51790const NG_PIPE_DEF = getClosureSafeProperty({ 51791 ɵpipe: getClosureSafeProperty 51792}); 51793const NG_MOD_DEF = getClosureSafeProperty({ 51794 ɵmod: getClosureSafeProperty 51795}); 51796const NG_FACTORY_DEF = getClosureSafeProperty({ 51797 ɵfac: getClosureSafeProperty 51798}); 51799/** 51800 * If a directive is diPublic, bloomAdd sets a property on the type with this constant as 51801 * the key and the directive's unique ID as the value. This allows us to map directives to their 51802 * bloom filter bit for DI. 51803 */ 51804// TODO(misko): This is wrong. The NG_ELEMENT_ID should never be minified. 51805 51806const NG_ELEMENT_ID = getClosureSafeProperty({ 51807 __NG_ELEMENT_ID__: getClosureSafeProperty 51808}); 51809/** 51810 * @license 51811 * Copyright Google LLC All Rights Reserved. 51812 * 51813 * Use of this source code is governed by an MIT-style license that can be 51814 * found in the LICENSE file at https://angular.io/license 51815 */ 51816 51817/** Counter used to generate unique IDs for component definitions. */ 51818 51819let componentDefCount = 0; 51820/** 51821 * Create a component definition object. 51822 * 51823 * 51824 * # Example 51825 * ``` 51826 * class MyDirective { 51827 * // Generated by Angular Template Compiler 51828 * // [Symbol] syntax will not be supported by TypeScript until v2.7 51829 * static ɵcmp = defineComponent({ 51830 * ... 51831 * }); 51832 * } 51833 * ``` 51834 * @codeGenApi 51835 */ 51836 51837function ɵɵdefineComponent(componentDefinition) { 51838 return noSideEffects(() => { 51839 // Initialize ngDevMode. This must be the first statement in ɵɵdefineComponent. 51840 // See the `initNgDevMode` docstring for more information. 51841 (typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode(); 51842 const type = componentDefinition.type; 51843 const standalone = componentDefinition.standalone === true; 51844 const declaredInputs = {}; 51845 const def = { 51846 type: type, 51847 providersResolver: null, 51848 decls: componentDefinition.decls, 51849 vars: componentDefinition.vars, 51850 factory: null, 51851 template: componentDefinition.template || null, 51852 consts: componentDefinition.consts || null, 51853 ngContentSelectors: componentDefinition.ngContentSelectors, 51854 hostBindings: componentDefinition.hostBindings || null, 51855 hostVars: componentDefinition.hostVars || 0, 51856 hostAttrs: componentDefinition.hostAttrs || null, 51857 contentQueries: componentDefinition.contentQueries || null, 51858 declaredInputs: declaredInputs, 51859 inputs: null, 51860 outputs: null, 51861 exportAs: componentDefinition.exportAs || null, 51862 onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush, 51863 directiveDefs: null, 51864 pipeDefs: null, 51865 standalone, 51866 dependencies: standalone && componentDefinition.dependencies || null, 51867 getStandaloneInjector: null, 51868 selectors: componentDefinition.selectors || EMPTY_ARRAY, 51869 viewQuery: componentDefinition.viewQuery || null, 51870 features: componentDefinition.features || null, 51871 data: componentDefinition.data || {}, 51872 encapsulation: componentDefinition.encapsulation || ViewEncapsulation$1.Emulated, 51873 id: `c${componentDefCount++}`, 51874 styles: componentDefinition.styles || EMPTY_ARRAY, 51875 _: null, 51876 setInput: null, 51877 schemas: componentDefinition.schemas || null, 51878 tView: null 51879 }; 51880 const dependencies = componentDefinition.dependencies; 51881 const feature = componentDefinition.features; 51882 def.inputs = invertObject(componentDefinition.inputs, declaredInputs), def.outputs = invertObject(componentDefinition.outputs), feature && feature.forEach(fn => fn(def));
51883 def.directiveDefs = dependencies ? () => (typeof dependencies === 'function' ? dependencies() : dependencies).map(extractDirectiveDef).filter(nonNull) : null; 51884 def.pipeDefs = dependencies ? () => (typeof dependencies === 'function' ? dependencies() : dependencies).map(getPipeDef$1).filter(nonNull) : null; 51885 return def; 51886 }); 51887} 51888/** 51889 * Generated next to NgModules to monkey-patch directive and pipe references onto a component's 51890 * definition, when generating a direct reference in the component file would otherwise create an 51891 * import cycle. 51892 * 51893 * See [this explanation](https://hackmd.io/Odw80D0pR6yfsOjg_7XCJg?view) for more details. 51894 * 51895 * @codeGenApi 51896 */ 51897 51898 51899function ɵɵsetComponentScope(type, directives, pipes) { 51900 const def = type.ɵcmp; 51901 51902 def.directiveDefs = () => (typeof directives === 'function' ? directives() : directives).map(extractDirectiveDef); 51903 51904 def.pipeDefs = () => (typeof pipes === 'function' ? pipes() : pipes).map(getPipeDef$1); 51905} 51906 51907function extractDirectiveDef(type) { 51908 return getComponentDef(type) || getDirectiveDef(type); 51909} 51910 51911function nonNull(value) { 51912 return value !== null; 51913} 51914/** 51915 * @codeGenApi 51916 */ 51917 51918 51919function ɵɵdefineNgModule(def) { 51920 return noSideEffects(() => { 51921 const res = { 51922 type: def.type, 51923 bootstrap: def.bootstrap || EMPTY_ARRAY, 51924 declarations: def.declarations || EMPTY_ARRAY, 51925 imports: def.imports || EMPTY_ARRAY, 51926 exports: def.exports || EMPTY_ARRAY, 51927 transitiveCompileScopes: null, 51928 schemas: def.schemas || null, 51929 id: def.id || null 51930 }; 51931 return res; 51932 }); 51933} 51934/** 51935 * Adds the module metadata that is necessary to compute the module's transitive scope to an 51936 * existing module definition. 51937 * 51938 * Scope metadata of modules is not used in production builds, so calls to this function can be 51939 * marked pure to tree-shake it from the bundle, allowing for all referenced declarations 51940 * to become eligible for tree-shaking as well. 51941 * 51942 * @codeGenApi 51943 */ 51944 51945 51946function ɵɵsetNgModuleScope(type, scope) { 51947 return noSideEffects(() => { 51948 const ngModuleDef = getNgModuleDef(type, true); 51949 ngModuleDef.declarations = scope.declarations || EMPTY_ARRAY; 51950 ngModuleDef.imports = scope.imports || EMPTY_ARRAY; 51951 ngModuleDef.exports = scope.exports || EMPTY_ARRAY; 51952 }); 51953} 51954/** 51955 * Inverts an inputs or outputs lookup such that the keys, which were the 51956 * minified keys, are part of the values, and the values are parsed so that 51957 * the publicName of the property is the new key 51958 * 51959 * e.g. for 51960 * 51961 * ``` 51962 * class Comp { 51963 * @Input() 51964 * propName1: string; 51965 * 51966 * @Input('publicName2') 51967 * declaredPropName2: number; 51968 * } 51969 * ``` 51970 * 51971 * will be serialized as 51972 * 51973 * ``` 51974 * { 51975 * propName1: 'propName1', 51976 * declaredPropName2: ['publicName2', 'declaredPropName2'], 51977 * } 51978 * ``` 51979 * 51980 * which is than translated by the minifier as: 51981 * 51982 * ``` 51983 * { 51984 * minifiedPropName1: 'propName1', 51985 * minifiedPropName2: ['publicName2', 'declaredPropName2'], 51986 * } 51987 * ``` 51988 * 51989 * becomes: (public name => minifiedName) 51990 * 51991 * ``` 51992 * { 51993 * 'propName1': 'minifiedPropName1', 51994 * 'publicName2': 'minifiedPropName2', 51995 * } 51996 * ``` 51997 * 51998 * Optionally the function can take `secondary` which will result in: (public name => declared name) 51999 * 52000 * ``` 52001 * { 52002 * 'propName1': 'propName1', 52003 * 'publicName2': 'declaredPropName2', 52004 * } 52005 * ``` 52006 * 52007 52008 */ 52009 52010 52011function invertObject(obj, secondary) { 52012 if (obj == null) return EMPTY_OBJ; 52013 const newLookup = {}; 52014 52015 for (const minifiedKey in obj) { 52016 if (obj.hasOwnProperty(minifiedKey)) { 52017 let publicName = obj[minifiedKey]; 52018 let declaredName = publicName; 52019 52020 if (Array.isArray(publicName)) { 52021 declaredName = publicName[1]; 52022 publicName = publicName[0]; 52023 } 52024 52025 newLookup[publicName] = minifiedKey; 52026 52027 if (secondary) { 52028 secondary[publicName] = declaredName; 52029 } 52030 } 52031 } 52032 52033 return newLookup; 52034} 52035/** 52036 * Create a directive definition object. 52037 * 52038 * # Example 52039 * ```ts 52040 * class MyDirective { 52041 * // Generated by Angular Template Compiler 52042 * // [Symbol] syntax will not be supported by TypeScript until v2.7 52043 * static ɵdir = ɵɵdefineDirective({ 52044 * ... 52045 * }); 52046 * } 52047 * ``` 52048 * 52049 * @codeGenApi 52050 */ 52051 52052 52053const ɵɵdefineDirective = ɵɵdefineComponent; 52054/** 52055 * Create a pipe definition object. 52056 * 52057 * # Example 52058 * ``` 52059 * class MyPipe implements PipeTransform { 52060 * // Generated by Angular Template Compiler 52061 * static ɵpipe = definePipe({ 52062 * ... 52063 * }); 52064 * } 52065 * ``` 52066 * @param pipeDef Pipe definition generated by the compiler 52067 * 52068 * @codeGenApi 52069 */ 52070 52071function ɵɵdefinePipe(pipeDef) { 52072 return { 52073 type: pipeDef.type, 52074 name: pipeDef.name, 52075 factory: null, 52076 pure: pipeDef.pure !== false, 52077 standalone: pipeDef.standalone === true, 52078 onDestroy: pipeDef.type.prototype.ngOnDestroy || null 52079 }; 52080} 52081/** 52082 * The following getter methods retrieve the definition from the type. Currently the retrieval 52083 * honors inheritance, but in the future we may change the rule to require that definitions are 52084 * explicit. This would require some sort of migration strategy. 52085 */ 52086 52087 52088function getComponentDef(type) { 52089 return type[NG_COMP_DEF] || null; 52090} 52091 52092function getDirectiveDef(type) { 52093 return type[NG_DIR_DEF] || null; 52094} 52095 52096function getPipeDef$1(type) { 52097 return type[NG_PIPE_DEF] || null; 52098} 52099 52100function isStandalone(type) { 52101 const def = getComponentDef(type) || getDirectiveDef(type) || getPipeDef$1(type); 52102 return def !== null ? def.standalone : false;
52103} 52104 52105function getNgModuleDef(type, throwNotFound) { 52106 const ngModuleDef = type[NG_MOD_DEF] || null; 52107 52108 if (!ngModuleDef && throwNotFound === true) { 52109 throw new Error(`Type ${stringify(type)} does not have 'ɵmod' property.`); 52110 } 52111 52112 return ngModuleDef; 52113} 52114/** 52115 * @license 52116 * Copyright Google LLC All Rights Reserved. 52117 * 52118 * Use of this source code is governed by an MIT-style license that can be 52119 * found in the LICENSE file at https://angular.io/license 52120 */ 52121// Below are constants for LView indices to help us look up LView members 52122// without having to remember the specific indices. 52123// Uglify will inline these when minifying so there shouldn't be a cost. 52124 52125 52126const HOST = 0; 52127const TVIEW = 1; 52128const FLAGS = 2; 52129const PARENT = 3; 52130const NEXT = 4; 52131const TRANSPLANTED_VIEWS_TO_REFRESH = 5; 52132const T_HOST = 6; 52133const CLEANUP = 7; 52134const CONTEXT = 8; 52135const INJECTOR$1 = 9; 52136const RENDERER_FACTORY = 10; 52137const RENDERER = 11; 52138const SANITIZER = 12; 52139const CHILD_HEAD = 13; 52140const CHILD_TAIL = 14; // FIXME(misko): Investigate if the three declarations aren't all same thing. 52141 52142const DECLARATION_VIEW = 15; 52143const DECLARATION_COMPONENT_VIEW = 16; 52144const DECLARATION_LCONTAINER = 17; 52145const PREORDER_HOOK_FLAGS = 18; 52146const QUERIES = 19; 52147const ID = 20; 52148const EMBEDDED_VIEW_INJECTOR = 21; 52149/** 52150 * Size of LView's header. Necessary to adjust for it when setting slots. 52151 * 52152 * IMPORTANT: `HEADER_OFFSET` should only be referred to the in the `ɵɵ*` instructions to translate 52153 * instruction index into `LView` index. All other indexes should be in the `LView` index space and 52154 * there should be no need to refer to `HEADER_OFFSET` anywhere else. 52155 */ 52156 52157const HEADER_OFFSET = 22; 52158/** 52159 * Converts `TViewType` into human readable text. 52160 * Make sure this matches with `TViewType` 52161 */ 52162 52163const TViewTypeAsString = ['Root', 'Component', 'Embedded' // 2 52164]; // Note: This hack is necessary so we don't erroneously get a circular dependency 52165// failure based on types. 52166 52167const unusedValueExportToPlacateAjd$8 = 1; 52168/** 52169 * @license 52170 * Copyright Google LLC All Rights Reserved. 52171 * 52172 * Use of this source code is governed by an MIT-style license that can be 52173 * found in the LICENSE file at https://angular.io/license 52174 */ 52175 52176/** 52177 * Special location which allows easy identification of type. If we have an array which was 52178 * retrieved from the `LView` and that array has `true` at `TYPE` location, we know it is 52179 * `LContainer`. 52180 */ 52181 52182const TYPE = 1; 52183/** 52184 * Below are constants for LContainer indices to help us look up LContainer members 52185 * without having to remember the specific indices. 52186 * Uglify will inline these when minifying so there shouldn't be a cost. 52187 */ 52188 52189/** 52190 * Flag to signify that this `LContainer` may have transplanted views which need to be change 52191 * detected. (see: `LView[DECLARATION_COMPONENT_VIEW])`. 52192 * 52193 * This flag, once set, is never unset for the `LContainer`. This means that when unset we can skip 52194 * a lot of work in `refreshEmbeddedViews`. But when set we still need to verify 52195 * that the `MOVED_VIEWS` are transplanted and on-push. 52196 */ 52197 52198const HAS_TRANSPLANTED_VIEWS = 2; // PARENT, NEXT, TRANSPLANTED_VIEWS_TO_REFRESH are indices 3, 4, and 5 52199// As we already have these constants in LView, we don't need to re-create them. 52200// T_HOST is index 6 52201// We already have this constants in LView, we don't need to re-create it. 52202 52203const NATIVE = 7; 52204const VIEW_REFS = 8; 52205const MOVED_VIEWS = 9; 52206/** 52207 * Size of LContainer's header. Represents the index after which all views in the 52208 * container will be inserted. We need to keep a record of current views so we know 52209 * which views are already in the DOM (and don't need to be re-added) and so we can 52210 * remove views from the DOM when they are no longer required. 52211 */ 52212 52213const CONTAINER_HEADER_OFFSET = 10; // Note: This hack is necessary so we don't erroneously get a circular dependency 52214// failure based on types. 52215 52216const unusedValueExportToPlacateAjd$7 = 1; 52217/** 52218 * @license 52219 * Copyright Google LLC All Rights Reserved. 52220 * 52221 * Use of this source code is governed by an MIT-style license that can be 52222 * found in the LICENSE file at https://angular.io/license 52223 */ 52224 52225/** 52226 * True if `value` is `LView`. 52227 * @param value wrapped value of `RNode`, `LView`, `LContainer` 52228 */ 52229 52230function isLView(value) { 52231 return Array.isArray(value) && typeof value[TYPE] === 'object'; 52232} 52233/** 52234 * True if `value` is `LContainer`. 52235 * @param value wrapped value of `RNode`, `LView`, `LContainer` 52236 */ 52237 52238 52239function isLContainer(value) { 52240 return Array.isArray(value) && value[TYPE] === true; 52241} 52242 52243function isContentQueryHost(tNode) { 52244 return (tNode.flags & 8 52245 /* TNodeFlags.hasContentQuery */ 52246 ) !== 0; 52247} 52248 52249function isComponentHost(tNode) { 52250 return (tNode.flags & 2 52251 /* TNodeFlags.isComponentHost */ 52252 ) === 2 52253 /* TNodeFlags.isComponentHost */ 52254 ; 52255} 52256 52257function isDirectiveHost(tNode) { 52258 return (tNode.flags & 1 52259 /* TNodeFlags.isDirectiveHost */ 52260 ) === 1 52261 /* TNodeFlags.isDirectiveHost */ 52262 ; 52263} 52264 52265function isComponentDef(def) { 52266 return def.template !== null; 52267} 52268 52269function isRootView(target) { 52270 return (target[FLAGS] & 256 52271 /* LViewFlags.IsRoot */ 52272 ) !== 0; 52273} 52274/** 52275 * @license 52276 * Copyright Google LLC All Rights Reserved. 52277 * 52278 * Use of this source code is governed by an MIT-style license that can be 52279 * found in the LICENSE file at https://angular.io/license 52280 */ 52281// [Assert functions do not constraint type when they are guarded by a truthy 52282// expression.](https://github.com/microsoft/TypeScript/issues/37295) 52283 52284 52285function assertTNodeForLView(tNode, lView) { 52286 assertTNodeForTView(tNode, lView[TVIEW]); 52287} 52288 52289function assertTNodeForTView(tNode, tView) { 52290 assertTNode(tNode); 52291 tNode.hasOwnProperty('tView_') && assertEqual(tNode.tView_, tView, 'This TNode does not belong to this TView.'); 52292} 52293 52294function assertTNode(tNode) { 52295 assertDefined(tNode, 'TNode must be defined'); 52296
vendor: 8,301 bytes, lines 52297-52550
52297 if (!(tNode && typeof tNode === 'object' && tNode.hasOwnProperty('directiveStylingLast'))) { 52298 throwError('Not of type TNode, got: ' + tNode); 52299 } 52300} 52301 52302function assertTIcu(tIcu) { 52303 assertDefined(tIcu, 'Expected TIcu to be defined'); 52304 52305 if (!(typeof tIcu.currentCaseLViewIndex === 'number')) { 52306 throwError('Object is not of TIcu type.'); 52307 } 52308} 52309 52310function assertComponentType(actual, msg = 'Type passed in is not ComponentType, it does not have \'ɵcmp\' property.') { 52311 if (!getComponentDef(actual)) { 52312 throwError(msg); 52313 } 52314} 52315 52316function assertNgModuleType(actual, msg = 'Type passed in is not NgModuleType, it does not have \'ɵmod\' property.') { 52317 if (!getNgModuleDef(actual)) { 52318 throwError(msg); 52319 } 52320} 52321 52322function assertCurrentTNodeIsParent(isParent) { 52323 assertEqual(isParent, true, 'currentTNode should be a parent'); 52324} 52325 52326function assertHasParent(tNode) { 52327 assertDefined(tNode, 'currentTNode should exist!'); 52328 assertDefined(tNode.parent, 'currentTNode should have a parent'); 52329} 52330 52331function assertDataNext(lView, index, arr) { 52332 if (arr == null) arr = lView; 52333 assertEqual(arr.length, index, `index ${index} expected to be at the end of arr (length ${arr.length})`); 52334} 52335 52336function assertLContainer(value) { 52337 assertDefined(value, 'LContainer must be defined'); 52338 assertEqual(isLContainer(value), true, 'Expecting LContainer'); 52339} 52340 52341function assertLViewOrUndefined(value) { 52342 value && assertEqual(isLView(value), true, 'Expecting LView or undefined or null'); 52343} 52344 52345function assertLView(value) { 52346 assertDefined(value, 'LView must be defined'); 52347 assertEqual(isLView(value), true, 'Expecting LView'); 52348} 52349 52350function assertFirstCreatePass(tView, errMessage) { 52351 assertEqual(tView.firstCreatePass, true, errMessage || 'Should only be called in first create pass.'); 52352} 52353 52354function assertFirstUpdatePass(tView, errMessage) { 52355 assertEqual(tView.firstUpdatePass, true, errMessage || 'Should only be called in first update pass.'); 52356} 52357/** 52358 * This is a basic sanity check that an object is probably a directive def. DirectiveDef is 52359 * an interface, so we can't do a direct instanceof check. 52360 */ 52361 52362 52363function assertDirectiveDef(obj) { 52364 if (obj.type === undefined || obj.selectors == undefined || obj.inputs === undefined) { 52365 throwError(`Expected a DirectiveDef/ComponentDef and this object does not seem to have the expected shape.`); 52366 } 52367} 52368 52369function assertIndexInDeclRange(lView, index) { 52370 const tView = lView[1]; 52371 assertBetween(HEADER_OFFSET, tView.bindingStartIndex, index); 52372} 52373 52374function assertIndexInVarsRange(lView, index) { 52375 const tView = lView[1]; 52376 assertBetween(tView.bindingStartIndex, tView.expandoStartIndex, index); 52377} 52378 52379function assertIndexInExpandoRange(lView, index) { 52380 const tView = lView[1]; 52381 assertBetween(tView.expandoStartIndex, lView.length, index); 52382} 52383 52384function assertBetween(lower, upper, index) { 52385 if (!(lower <= index && index < upper)) { 52386 throwError(`Index out of range (expecting ${lower} <= ${index} < ${upper})`); 52387 } 52388} 52389 52390function assertProjectionSlots(lView, errMessage) { 52391 assertDefined(lView[DECLARATION_COMPONENT_VIEW], 'Component views should exist.'); 52392 assertDefined(lView[DECLARATION_COMPONENT_VIEW][T_HOST].projection, errMessage || 'Components with projection nodes (<ng-content>) must have projection slots defined.'); 52393} 52394 52395function assertParentView(lView, errMessage) { 52396 assertDefined(lView, errMessage || 'Component views should always have a parent view (component\'s host view)'); 52397} 52398/** 52399 * This is a basic sanity check that the `injectorIndex` seems to point to what looks like a 52400 * NodeInjector data structure. 52401 * 52402 * @param lView `LView` which should be checked. 52403 * @param injectorIndex index into the `LView` where the `NodeInjector` is expected. 52404 */ 52405 52406 52407function assertNodeInjector(lView, injectorIndex) { 52408 assertIndexInExpandoRange(lView, injectorIndex); 52409 assertIndexInExpandoRange(lView, injectorIndex + 8 52410 /* NodeInjectorOffset.PARENT */ 52411 ); 52412 assertNumber(lView[injectorIndex + 0], 'injectorIndex should point to a bloom filter'); 52413 assertNumber(lView[injectorIndex + 1], 'injectorIndex should point to a bloom filter'); 52414 assertNumber(lView[injectorIndex + 2], 'injectorIndex should point to a bloom filter'); 52415 assertNumber(lView[injectorIndex + 3], 'injectorIndex should point to a bloom filter'); 52416 assertNumber(lView[injectorIndex + 4], 'injectorIndex should point to a bloom filter'); 52417 assertNumber(lView[injectorIndex + 5], 'injectorIndex should point to a bloom filter'); 52418 assertNumber(lView[injectorIndex + 6], 'injectorIndex should point to a bloom filter'); 52419 assertNumber(lView[injectorIndex + 7], 'injectorIndex should point to a bloom filter'); 52420 assertNumber(lView[injectorIndex + 8 52421 /* NodeInjectorOffset.PARENT */ 52422 ], 'injectorIndex should point to parent injector'); 52423} 52424/** 52425 * @license 52426 * Copyright Google LLC All Rights Reserved. 52427 * 52428 * Use of this source code is governed by an MIT-style license that can be 52429 * found in the LICENSE file at https://angular.io/license 52430 */ 52431 52432 52433function getFactoryDef(type, throwNotFound) { 52434 const hasFactoryDef = type.hasOwnProperty(NG_FACTORY_DEF); 52435 52436 if (!hasFactoryDef && throwNotFound === true && ngDevMode) { 52437 throw new Error(`Type ${stringify(type)} does not have 'ɵfac' property.`); 52438 } 52439 52440 return hasFactoryDef ? type[NG_FACTORY_DEF] : null; 52441} 52442/** 52443 * @license 52444 * Copyright Google LLC All Rights Reserved. 52445 * 52446 * Use of this source code is governed by an MIT-style license that can be 52447 * found in the LICENSE file at https://angular.io/license 52448 */ 52449 52450/** 52451 * Represents a basic change from a previous to a new value for a single 52452 * property on a directive instance. Passed as a value in a 52453 * {@link SimpleChanges} object to the `ngOnChanges` hook. 52454 * 52455 * @see `OnChanges` 52456 * 52457 * @publicApi 52458 */ 52459 52460 52461class SimpleChange { 52462 constructor(previousValue, currentValue, firstChange) { 52463 this.previousValue = previousValue; 52464 this.currentValue = currentValue; 52465 this.firstChange = firstChange; 52466 } 52467 /** 52468 * Check whether the new value is the first value assigned. 52469 */ 52470 52471 52472 isFirstChange() { 52473 return this.firstChange; 52474 } 52475 52476} 52477/** 52478 * @license 52479 * Copyright Google LLC All Rights Reserved. 52480 * 52481 * Use of this source code is governed by an MIT-style license that can be 52482 * found in the LICENSE file at https://angular.io/license 52483 */ 52484 52485/** 52486 * The NgOnChangesFeature decorates a component with support for the ngOnChanges 52487 * lifecycle hook, so it should be included in any component that implements 52488 * that hook. 52489 * 52490 * If the component or directive uses inheritance, the NgOnChangesFeature MUST 52491 * be included as a feature AFTER {@link InheritDefinitionFeature}, otherwise 52492 * inherited properties will not be propagated to the ngOnChanges lifecycle 52493 * hook. 52494 * 52495 * Example usage: 52496 * 52497 * ``` 52498 * static ɵcmp = defineComponent({ 52499 * ... 52500 * inputs: {name: 'publicName'}, 52501 * features: [NgOnChangesFeature] 52502 * }); 52503 * ``` 52504 * 52505 * @codeGenApi 52506 */ 52507 52508 52509function ɵɵNgOnChangesFeature() { 52510 return NgOnChangesFeatureImpl; 52511} 52512 52513function NgOnChangesFeatureImpl(definition) { 52514 if (definition.type.prototype.ngOnChanges) { 52515 definition.setInput = ngOnChangesSetInput; 52516 } 52517 52518 return rememberChangeHistoryAndInvokeOnChangesHook; 52519} // This option ensures that the ngOnChanges lifecycle hook will be inherited 52520// from superclasses (in InheritDefinitionFeature). 52521 52522/** @nocollapse */ 52523// tslint:disable-next-line:no-toplevel-property-access 52524 52525 52526ɵɵNgOnChangesFeature.ngInherit = true; 52527/** 52528 * This is a synthetic lifecycle hook which gets inserted into `TView.preOrderHooks` to simulate 52529 * `ngOnChanges`. 52530 * 52531 * The hook reads the `NgSimpleChangesStore` data from the component instance and if changes are 52532 * found it invokes `ngOnChanges` on the component instance. 52533 * 52534 * @param this Component instance. Because this function gets inserted into `TView.preOrderHooks`, 52535 * it is guaranteed to be called with component instance. 52536 */ 52537 52538function rememberChangeHistoryAndInvokeOnChangesHook() { 52539 const simpleChangesStore = getSimpleChangesStore(this); 52540 const current = simpleChangesStore?.current; 52541 52542 if (current) { 52543 const previous = simpleChangesStore.previous; 52544 52545 if (previous === EMPTY_OBJ) { 52546 simpleChangesStore.previous = current; 52547 } else { 52548 // New changes are copied to the previous store, so that we don't lose history for inputs 52549 // which were not changed this time 52550 for (let key in current) {
52551 previous[key] = current[key]; 52552 } 52553 } 52554 52555 simpleChangesStore.current = null; 52556 this.ngOnChanges(current); 52557 } 52558} 52559 52560function ngOnChangesSetInput(instance, value, publicName, privateName) { 52561 const simpleChangesStore = getSimpleChangesStore(instance) || setSimpleChangesStore(instance, { 52562 previous: EMPTY_OBJ, 52563 current: null 52564 }); 52565 const current = simpleChangesStore.current || (simpleChangesStore.current = {}); 52566 const previous = simpleChangesStore.previous; 52567 const declaredName = this.declaredInputs[publicName]; 52568 const previousChange = previous[declaredName]; 52569 current[declaredName] = new SimpleChange(previousChange && previousChange.currentValue, value, previous === EMPTY_OBJ); 52570 instance[privateName] = value; 52571} 52572 52573const SIMPLE_CHANGES_STORE = '__ngSimpleChanges__'; 52574 52575function getSimpleChangesStore(instance) { 52576 return instance[SIMPLE_CHANGES_STORE] || null; 52577} 52578 52579function setSimpleChangesStore(instance, store) { 52580 return instance[SIMPLE_CHANGES_STORE] = store; 52581} 52582/** 52583 * @license 52584 * Copyright Google LLC All Rights Reserved. 52585 * 52586 * Use of this source code is governed by an MIT-style license that can be 52587 * found in the LICENSE file at https://angular.io/license 52588 */ 52589 52590 52591let profilerCallback = null; 52592/** 52593 * Sets the callback function which will be invoked before and after performing certain actions at 52594 * runtime (for example, before and after running change detection). 52595 * 52596 * Warning: this function is *INTERNAL* and should not be relied upon in application's code. 52597 * The contract of the function might be changed in any release and/or the function can be removed 52598 * completely. 52599 * 52600 * @param profiler function provided by the caller or null value to disable profiling. 52601 */ 52602 52603const setProfiler = profiler => { 52604 profilerCallback = profiler; 52605}; 52606/** 52607 * Profiler function which wraps user code executed by the runtime. 52608 * 52609 * @param event ProfilerEvent corresponding to the execution context 52610 * @param instance component instance 52611 * @param hookOrListener lifecycle hook function or output listener. The value depends on the 52612 * execution context 52613 * @returns 52614 */ 52615 52616 52617const profiler = function (event, instance, hookOrListener) { 52618 if (profilerCallback != null 52619 /* both `null` and `undefined` */ 52620 ) { 52621 profilerCallback(event, instance, hookOrListener); 52622 } 52623}; 52624/** 52625 * @license 52626 * Copyright Google LLC All Rights Reserved. 52627 * 52628 * Use of this source code is governed by an MIT-style license that can be 52629 * found in the LICENSE file at https://angular.io/license 52630 */ 52631 52632 52633const SVG_NAMESPACE = 'svg'; 52634const SVG_NAMESPACE_URI = 'http://www.w3.org/2000/svg'; 52635const MATH_ML_NAMESPACE = 'math'; 52636const MATH_ML_NAMESPACE_URI = 'http://www.w3.org/1998/MathML/'; 52637 52638function getNamespaceUri(namespace) { 52639 const name = namespace.toLowerCase(); 52640 return name === SVG_NAMESPACE ? SVG_NAMESPACE_URI : name === MATH_ML_NAMESPACE ? MATH_ML_NAMESPACE_URI : null; 52641} 52642/** 52643 * @license 52644 * Copyright Google LLC All Rights Reserved. 52645 * 52646 * Use of this source code is governed by an MIT-style license that can be 52647 * found in the LICENSE file at https://angular.io/license 52648 */ 52649 52650/** 52651 * For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`) 52652 * in same location in `LView`. This is because we don't want to pre-allocate space for it 52653 * because the storage is sparse. This file contains utilities for dealing with such data types. 52654 * 52655 * How do we know what is stored at a given location in `LView`. 52656 * - `Array.isArray(value) === false` => `RNode` (The normal storage value) 52657 * - `Array.isArray(value) === true` => then the `value[0]` represents the wrapped value. 52658 * - `typeof value[TYPE] === 'object'` => `LView` 52659 * - This happens when we have a component at a given location 52660 * - `typeof value[TYPE] === true` => `LContainer` 52661 * - This happens when we have `LContainer` binding at a given location. 52662 * 52663 * 52664 * NOTE: it is assumed that `Array.isArray` and `typeof` operations are very efficient. 52665 */ 52666 52667/** 52668 * Returns `RNode`. 52669 * @param value wrapped value of `RNode`, `LView`, `LContainer` 52670 */ 52671 52672 52673function unwrapRNode(value) { 52674 while (Array.isArray(value)) { 52675 value = value[HOST]; 52676 } 52677 52678 return value; 52679} 52680/** 52681 * Returns `LView` or `null` if not found. 52682 * @param value wrapped value of `RNode`, `LView`, `LContainer` 52683 */ 52684 52685 52686function unwrapLView(value) { 52687 while (Array.isArray(value)) { 52688 // This check is same as `isLView()` but we don't call at as we don't want to call 52689 // `Array.isArray()` twice and give JITer more work for inlining. 52690 if (typeof value[TYPE] === 'object') return value; 52691 value = value[HOST]; 52692 } 52693 52694 return null; 52695} 52696/** 52697 * Returns `LContainer` or `null` if not found. 52698 * @param value wrapped value of `RNode`, `LView`, `LContainer` 52699 */ 52700 52701 52702function unwrapLContainer(value) { 52703 while (Array.isArray(value)) { 52704 // This check is same as `isLContainer()` but we don't call at as we don't want to call 52705 // `Array.isArray()` twice and give JITer more work for inlining. 52706 if (value[TYPE] === true) return value; 52707 value = value[HOST]; 52708 } 52709 52710 return null; 52711} 52712/** 52713 * Retrieves an element value from the provided `viewData`, by unwrapping 52714 * from any containers, component views, or style contexts. 52715 */ 52716 52717 52718function getNativeByIndex(index, lView) { 52719 ngDevMode && assertIndexInRange(lView, index); 52720 ngDevMode && assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Expected to be past HEADER_OFFSET'); 52721 return unwrapRNode(lView[index]); 52722} 52723/** 52724 * Retrieve an `RNode` for a given `TNode` and `LView`. 52725 * 52726 * This function guarantees in dev mode to retrieve a non-null `RNode`. 52727 * 52728 * @param tNode 52729 * @param lView 52730 */ 52731 52732 52733function getNativeByTNode(tNode, lView) { 52734 ngDevMode && assertTNodeForLView(tNode, lView); 52735 ngDevMode && assertIndexInRange(lView, tNode.index); 52736 const node = unwrapRNode(lView[tNode.index]); 52737 return node; 52738} 52739/** 52740 * Retrieve an `RNode` or `null` for a given `TNode` and `LView`. 52741 * 52742 * Some `TNode`s don't have associated `RNode`s. For example `Projection` 52743 * 52744 * @param tNode 52745 * @param lView 52746 */ 52747 52748 52749function getNativeByTNodeOrNull(tNode, lView) { 52750 const index = tNode === null ? -1 : tNode.index; 52751 52752 if (index !== -1) { 52753 ngDevMode && assertTNodeForLView(tNode, lView); 52754 const node = unwrapRNode(lView[index]); 52755 return node; 52756 } 52757 52758 return null; 52759} // fixme(misko): The return Type should be `TNode|null` 52760 52761 52762function getTNode(tView, index) { 52763 ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode'); 52764 ngDevMode && assertLessThan(index, tView.data.length, 'wrong index for TNode'); 52765 const tNode = tView.data[index];
52766 ngDevMode && tNode !== null && assertTNode(tNode); 52767 return tNode; 52768} 52769/** Retrieves a value from any `LView` or `TData`. */ 52770 52771 52772function load(view, index) { 52773 ngDevMode && assertIndexInRange(view, index); 52774 return view[index]; 52775} 52776 52777function getComponentLViewByIndex(nodeIndex, hostView) { 52778 // Could be an LView or an LContainer. If LContainer, unwrap to find LView. 52779 ngDevMode && assertIndexInRange(hostView, nodeIndex); 52780 const slotValue = hostView[nodeIndex]; 52781 const lView = isLView(slotValue) ? slotValue : slotValue[HOST]; 52782 return lView; 52783} 52784/** Checks whether a given view is in creation mode */ 52785 52786 52787function isCreationMode(view) { 52788 return (view[FLAGS] & 4 52789 /* LViewFlags.CreationMode */ 52790 ) === 4 52791 /* LViewFlags.CreationMode */ 52792 ; 52793} 52794/** 52795 * Returns a boolean for whether the view is attached to the change detection tree. 52796 * 52797 * Note: This determines whether a view should be checked, not whether it's inserted 52798 * into a container. For that, you'll want `viewAttachedToContainer` below. 52799 */ 52800 52801 52802function viewAttachedToChangeDetector(view) { 52803 return (view[FLAGS] & 64 52804 /* LViewFlags.Attached */ 52805 ) === 64 52806 /* LViewFlags.Attached */ 52807 ; 52808} 52809/** Returns a boolean for whether the view is attached to a container. */ 52810 52811 52812function viewAttachedToContainer(view) { 52813 return isLContainer(view[PARENT]); 52814} 52815 52816function getConstant(consts, index) { 52817 if (index === null || index === undefined) return null; 52818 ngDevMode && assertIndexInRange(consts, index); 52819 return consts[index]; 52820} 52821/** 52822 * Resets the pre-order hook flags of the view. 52823 * @param lView the LView on which the flags are reset 52824 */ 52825 52826 52827function resetPreOrderHookFlags(lView) { 52828 lView[PREORDER_HOOK_FLAGS] = 0; 52829} 52830/** 52831 * Updates the `TRANSPLANTED_VIEWS_TO_REFRESH` counter on the `LContainer` as well as the parents 52832 * whose 52833 * 1. counter goes from 0 to 1, indicating that there is a new child that has a view to refresh 52834 * or 52835 * 2. counter goes from 1 to 0, indicating there are no more descendant views to refresh 52836 */ 52837 52838 52839function updateTransplantedViewCount(lContainer, amount) { 52840 lContainer[TRANSPLANTED_VIEWS_TO_REFRESH] += amount; 52841 let viewOrContainer = lContainer; 52842 let parent = lContainer[PARENT]; 52843 52844 while (parent !== null && (amount === 1 && viewOrContainer[TRANSPLANTED_VIEWS_TO_REFRESH] === 1 || amount === -1 && viewOrContainer[TRANSPLANTED_VIEWS_TO_REFRESH] === 0)) { 52845 parent[TRANSPLANTED_VIEWS_TO_REFRESH] += amount; 52846 viewOrContainer = parent; 52847 parent = parent[PARENT]; 52848 } 52849} 52850/** 52851 * @license 52852 * Copyright Google LLC All Rights Reserved. 52853 * 52854 * Use of this source code is governed by an MIT-style license that can be 52855 * found in the LICENSE file at https://angular.io/license 52856 */ 52857 52858 52859const instructionState = { 52860 lFrame: createLFrame(null), 52861 bindingsEnabled: true 52862}; 52863/** 52864 * In this mode, any changes in bindings will throw an ExpressionChangedAfterChecked error. 52865 * 52866 * Necessary to support ChangeDetectorRef.checkNoChanges(). 52867 * 52868 * The `checkNoChanges` function is invoked only in ngDevMode=true and verifies that no unintended 52869 * changes exist in the change detector or its children. 52870 */ 52871 52872let _isInCheckNoChangesMode = false; 52873/** 52874 * Returns true if the instruction state stack is empty. 52875 * 52876 * Intended to be called from tests only (tree shaken otherwise). 52877 */ 52878 52879function specOnlyIsInstructionStateEmpty() { 52880 return instructionState.lFrame.parent === null; 52881} 52882 52883function getElementDepthCount() { 52884 return instructionState.lFrame.elementDepthCount; 52885} 52886 52887function increaseElementDepthCount() { 52888 instructionState.lFrame.elementDepthCount++; 52889} 52890 52891function decreaseElementDepthCount() { 52892 instructionState.lFrame.elementDepthCount--; 52893} 52894 52895function getBindingsEnabled() { 52896 return instructionState.bindingsEnabled; 52897} 52898/** 52899 * Enables directive matching on elements. 52900 * 52901 * * Example: 52902 * ``` 52903 * <my-comp my-directive> 52904 * Should match component / directive. 52905 * </my-comp> 52906 * <div ngNonBindable> 52907 * <!-- ɵɵdisableBindings() --> 52908 * <my-comp my-directive> 52909 * Should not match component / directive because we are in ngNonBindable. 52910 * </my-comp> 52911 * <!-- ɵɵenableBindings() --> 52912 * </div> 52913 * ``` 52914 * 52915 * @codeGenApi 52916 */ 52917 52918 52919function ɵɵenableBindings() { 52920 instructionState.bindingsEnabled = true; 52921} 52922/** 52923 * Disables directive matching on element. 52924 * 52925 * * Example: 52926 * ``` 52927 * <my-comp my-directive> 52928 * Should match component / directive. 52929 * </my-comp> 52930 * <div ngNonBindable> 52931 * <!-- ɵɵdisableBindings() --> 52932 * <my-comp my-directive> 52933 * Should not match component / directive because we are in ngNonBindable. 52934 * </my-comp> 52935 * <!-- ɵɵenableBindings() --> 52936 * </div> 52937 * ``` 52938 * 52939 * @codeGenApi 52940 */ 52941 52942 52943function ɵɵdisableBindings() { 52944 instructionState.bindingsEnabled = false;
vendor: 6,419 bytes, lines 52945-53175
52945} 52946/** 52947 * Return the current `LView`. 52948 */ 52949 52950 52951function getLView() { 52952 return instructionState.lFrame.lView; 52953} 52954/** 52955 * Return the current `TView`. 52956 */ 52957 52958 52959function getTView() { 52960 return instructionState.lFrame.tView; 52961} 52962/** 52963 * Restores `contextViewData` to the given OpaqueViewState instance. 52964 * 52965 * Used in conjunction with the getCurrentView() instruction to save a snapshot 52966 * of the current view and restore it when listeners are invoked. This allows 52967 * walking the declaration view tree in listeners to get vars from parent views. 52968 * 52969 * @param viewToRestore The OpaqueViewState instance to restore. 52970 * @returns Context of the restored OpaqueViewState instance. 52971 * 52972 * @codeGenApi 52973 */ 52974 52975 52976function ɵɵrestoreView(viewToRestore) { 52977 instructionState.lFrame.contextLView = viewToRestore; 52978 return viewToRestore[CONTEXT]; 52979} 52980/** 52981 * Clears the view set in `ɵɵrestoreView` from memory. Returns the passed in 52982 * value so that it can be used as a return value of an instruction. 52983 * 52984 * @codeGenApi 52985 */ 52986 52987 52988function ɵɵresetView(value) { 52989 instructionState.lFrame.contextLView = null; 52990 return value; 52991} 52992 52993function getCurrentTNode() { 52994 let currentTNode = getCurrentTNodePlaceholderOk(); 52995 52996 while (currentTNode !== null && currentTNode.type === 64 52997 /* TNodeType.Placeholder */ 52998 ) { 52999 currentTNode = currentTNode.parent; 53000 } 53001 53002 return currentTNode; 53003} 53004 53005function getCurrentTNodePlaceholderOk() { 53006 return instructionState.lFrame.currentTNode; 53007} 53008 53009function getCurrentParentTNode() { 53010 const lFrame = instructionState.lFrame; 53011 const currentTNode = lFrame.currentTNode; 53012 return lFrame.isParent ? currentTNode : currentTNode.parent; 53013} 53014 53015function setCurrentTNode(tNode, isParent) { 53016 ngDevMode && tNode && assertTNodeForTView(tNode, instructionState.lFrame.tView); 53017 const lFrame = instructionState.lFrame; 53018 lFrame.currentTNode = tNode; 53019 lFrame.isParent = isParent; 53020} 53021 53022function isCurrentTNodeParent() { 53023 return instructionState.lFrame.isParent; 53024} 53025 53026function setCurrentTNodeAsNotParent() { 53027 instructionState.lFrame.isParent = false; 53028} 53029 53030function setCurrentTNodeAsParent() { 53031 instructionState.lFrame.isParent = true; 53032} 53033 53034function getContextLView() { 53035 const contextLView = instructionState.lFrame.contextLView; 53036 ngDevMode && assertDefined(contextLView, 'contextLView must be defined.'); 53037 return contextLView; 53038} 53039 53040function isInCheckNoChangesMode() { 53041 !ngDevMode && throwError('Must never be called in production mode'); 53042 return _isInCheckNoChangesMode; 53043} 53044 53045function setIsInCheckNoChangesMode(mode) { 53046 !ngDevMode && throwError('Must never be called in production mode'); 53047 _isInCheckNoChangesMode = mode; 53048} // top level variables should not be exported for performance reasons (PERF_NOTES.md) 53049 53050 53051function getBindingRoot() { 53052 const lFrame = instructionState.lFrame; 53053 let index = lFrame.bindingRootIndex; 53054 53055 if (index === -1) { 53056 index = lFrame.bindingRootIndex = lFrame.tView.bindingStartIndex; 53057 } 53058 53059 return index; 53060} 53061 53062function getBindingIndex() { 53063 return instructionState.lFrame.bindingIndex; 53064} 53065 53066function setBindingIndex(value) { 53067 return instructionState.lFrame.bindingIndex = value; 53068} 53069 53070function nextBindingIndex() { 53071 return instructionState.lFrame.bindingIndex++; 53072} 53073 53074function incrementBindingIndex(count) { 53075 const lFrame = instructionState.lFrame; 53076 const index = lFrame.bindingIndex; 53077 lFrame.bindingIndex = lFrame.bindingIndex + count; 53078 return index; 53079} 53080 53081function isInI18nBlock() { 53082 return instructionState.lFrame.inI18n; 53083} 53084 53085function setInI18nBlock(isInI18nBlock) { 53086 instructionState.lFrame.inI18n = isInI18nBlock; 53087} 53088/** 53089 * Set a new binding root index so that host template functions can execute. 53090 * 53091 * Bindings inside the host template are 0 index. But because we don't know ahead of time 53092 * how many host bindings we have we can't pre-compute them. For this reason they are all 53093 * 0 index and we just shift the root so that they match next available location in the LView. 53094 * 53095 * @param bindingRootIndex Root index for `hostBindings` 53096 * @param currentDirectiveIndex `TData[currentDirectiveIndex]` will point to the current directive 53097 * whose `hostBindings` are being processed. 53098 */ 53099 53100 53101function setBindingRootForHostBindings(bindingRootIndex, currentDirectiveIndex) { 53102 const lFrame = instructionState.lFrame; 53103 lFrame.bindingIndex = lFrame.bindingRootIndex = bindingRootIndex; 53104 setCurrentDirectiveIndex(currentDirectiveIndex); 53105} 53106/** 53107 * When host binding is executing this points to the directive index. 53108 * `TView.data[getCurrentDirectiveIndex()]` is `DirectiveDef` 53109 * `LView[getCurrentDirectiveIndex()]` is directive instance. 53110 */ 53111 53112 53113function getCurrentDirectiveIndex() { 53114 return instructionState.lFrame.currentDirectiveIndex; 53115} 53116/** 53117 * Sets an index of a directive whose `hostBindings` are being processed. 53118 * 53119 * @param currentDirectiveIndex `TData` index where current directive instance can be found. 53120 */ 53121 53122 53123function setCurrentDirectiveIndex(currentDirectiveIndex) { 53124 instructionState.lFrame.currentDirectiveIndex = currentDirectiveIndex; 53125} 53126/** 53127 * Retrieve the current `DirectiveDef` which is active when `hostBindings` instruction is being 53128 * executed. 53129 * 53130 * @param tData Current `TData` where the `DirectiveDef` will be looked up at. 53131 */ 53132 53133 53134function getCurrentDirectiveDef(tData) { 53135 const currentDirectiveIndex = instructionState.lFrame.currentDirectiveIndex; 53136 return currentDirectiveIndex === -1 ? null : tData[currentDirectiveIndex]; 53137} 53138 53139function getCurrentQueryIndex() { 53140 return instructionState.lFrame.currentQueryIndex; 53141} 53142 53143function setCurrentQueryIndex(value) { 53144 instructionState.lFrame.currentQueryIndex = value; 53145} 53146/** 53147 * Returns a `TNode` of the location where the current `LView` is declared at. 53148 * 53149 * @param lView an `LView` that we want to find parent `TNode` for. 53150 */ 53151 53152 53153function getDeclarationTNode(lView) { 53154 const tView = lView[TVIEW]; // Return the declaration parent for embedded views 53155 53156 if (tView.type === 2 53157 /* TViewType.Embedded */ 53158 ) { 53159 ngDevMode && assertDefined(tView.declTNode, 'Embedded TNodes should have declaration parents.'); 53160 return tView.declTNode; 53161 } // Components don't have `TView.declTNode` because each instance of component could be 53162 // inserted in different location, hence `TView.declTNode` is meaningless. 53163 // Falling back to `T_HOST` in case we cross component boundary. 53164 53165 53166 if (tView.type === 1 53167 /* TViewType.Component */ 53168 ) { 53169 return lView[T_HOST]; 53170 } // Remaining TNode type is `TViewType.Root` which doesn't have a parent TNode. 53171 53172 53173 return null; 53174} 53175/**
53176 * This is a light weight version of the `enterView` which is needed by the DI system. 53177 * 53178 * @param lView `LView` location of the DI context. 53179 * @param tNode `TNode` for DI context 53180 * @param flags DI context flags. if `SkipSelf` flag is set than we walk up the declaration 53181 * tree from `tNode` until we find parent declared `TElementNode`. 53182 * @returns `true` if we have successfully entered DI associated with `tNode` (or with declared 53183 * `TNode` if `flags` has `SkipSelf`). Failing to enter DI implies that no associated 53184 * `NodeInjector` can be found and we should instead use `ModuleInjector`. 53185 * - If `true` than this call must be fallowed by `leaveDI` 53186 * - If `false` than this call failed and we should NOT call `leaveDI` 53187 */ 53188 53189 53190function enterDI(lView, tNode, flags) { 53191 ngDevMode && assertLViewOrUndefined(lView); 53192 53193 if (flags & InjectFlags.SkipSelf) { 53194 ngDevMode && assertTNodeForTView(tNode, lView[TVIEW]); 53195 let parentTNode = tNode; 53196 let parentLView = lView; 53197 53198 while (true) { 53199 ngDevMode && assertDefined(parentTNode, 'Parent TNode should be defined'); 53200 parentTNode = parentTNode.parent; 53201 53202 if (parentTNode === null && !(flags & InjectFlags.Host)) { 53203 parentTNode = getDeclarationTNode(parentLView); 53204 if (parentTNode === null) break; // In this case, a parent exists and is definitely an element. So it will definitely 53205 // have an existing lView as the declaration view, which is why we can assume it's defined. 53206 53207 ngDevMode && assertDefined(parentLView, 'Parent LView should be defined'); 53208 parentLView = parentLView[DECLARATION_VIEW]; // In Ivy there are Comment nodes that correspond to ngIf and NgFor embedded directives 53209 // We want to skip those and look only at Elements and ElementContainers to ensure 53210 // we're looking at true parent nodes, and not content or other types. 53211 53212 if (parentTNode.type & (2 53213 /* TNodeType.Element */ 53214 | 8 53215 /* TNodeType.ElementContainer */ 53216 )) { 53217 break; 53218 } 53219 } else { 53220 break; 53221 } 53222 } 53223 53224 if (parentTNode === null) { 53225 // If we failed to find a parent TNode this means that we should use module injector. 53226 return false; 53227 } else { 53228 tNode = parentTNode; 53229 lView = parentLView; 53230 } 53231 } 53232 53233 ngDevMode && assertTNodeForLView(tNode, lView); 53234 const lFrame = instructionState.lFrame = allocLFrame(); 53235 lFrame.currentTNode = tNode; 53236 lFrame.lView = lView; 53237 return true; 53238} 53239/** 53240 * Swap the current lView with a new lView. 53241 * 53242 * For performance reasons we store the lView in the top level of the module. 53243 * This way we minimize the number of properties to read. Whenever a new view 53244 * is entered we have to store the lView for later, and when the view is 53245 * exited the state has to be restored 53246 * 53247 * @param newView New lView to become active 53248 * @returns the previously active lView; 53249 */ 53250 53251 53252function enterView(newView) { 53253 ngDevMode && assertNotEqual(newView[0], newView[1], '????'); 53254 ngDevMode && assertLViewOrUndefined(newView); 53255 const newLFrame = allocLFrame(); 53256 53257 if (ngDevMode) { 53258 assertEqual(newLFrame.isParent, true, 'Expected clean LFrame'); 53259 assertEqual(newLFrame.lView, null, 'Expected clean LFrame'); 53260 assertEqual(newLFrame.tView, null, 'Expected clean LFrame'); 53261 assertEqual(newLFrame.selectedIndex, -1, 'Expected clean LFrame'); 53262 assertEqual(newLFrame.elementDepthCount, 0, 'Expected clean LFrame'); 53263 assertEqual(newLFrame.currentDirectiveIndex, -1, 'Expected clean LFrame'); 53264 assertEqual(newLFrame.currentNamespace, null, 'Expected clean LFrame'); 53265 assertEqual(newLFrame.bindingRootIndex, -1, 'Expected clean LFrame'); 53266 assertEqual(newLFrame.currentQueryIndex, 0, 'Expected clean LFrame'); 53267 } 53268 53269 const tView = newView[TVIEW]; 53270 instructionState.lFrame = newLFrame; 53271 ngDevMode && tView.firstChild && assertTNodeForTView(tView.firstChild, tView); 53272 newLFrame.currentTNode = tView.firstChild; 53273 newLFrame.lView = newView; 53274 newLFrame.tView = tView; 53275 newLFrame.contextLView = newView; 53276 newLFrame.bindingIndex = tView.bindingStartIndex; 53277 newLFrame.inI18n = false;
vendor: 5,526 bytes, lines 53278-53471
53278} 53279/** 53280 * Allocates next free LFrame. This function tries to reuse the `LFrame`s to lower memory pressure. 53281 */ 53282 53283 53284function allocLFrame() { 53285 const currentLFrame = instructionState.lFrame; 53286 const childLFrame = currentLFrame === null ? null : currentLFrame.child; 53287 const newLFrame = childLFrame === null ? createLFrame(currentLFrame) : childLFrame; 53288 return newLFrame; 53289} 53290 53291function createLFrame(parent) { 53292 const lFrame = { 53293 currentTNode: null, 53294 isParent: true, 53295 lView: null, 53296 tView: null, 53297 selectedIndex: -1, 53298 contextLView: null, 53299 elementDepthCount: 0, 53300 currentNamespace: null, 53301 currentDirectiveIndex: -1, 53302 bindingRootIndex: -1, 53303 bindingIndex: -1, 53304 currentQueryIndex: 0, 53305 parent: parent, 53306 child: null, 53307 inI18n: false 53308 }; 53309 parent !== null && (parent.child = lFrame); // link the new LFrame for reuse. 53310 53311 return lFrame; 53312} 53313/** 53314 * A lightweight version of leave which is used with DI. 53315 * 53316 * This function only resets `currentTNode` and `LView` as those are the only properties 53317 * used with DI (`enterDI()`). 53318 * 53319 * NOTE: This function is reexported as `leaveDI`. However `leaveDI` has return type of `void` where 53320 * as `leaveViewLight` has `LFrame`. This is so that `leaveViewLight` can be used in `leaveView`. 53321 */ 53322 53323 53324function leaveViewLight() { 53325 const oldLFrame = instructionState.lFrame; 53326 instructionState.lFrame = oldLFrame.parent; 53327 oldLFrame.currentTNode = null; 53328 oldLFrame.lView = null; 53329 return oldLFrame; 53330} 53331/** 53332 * This is a lightweight version of the `leaveView` which is needed by the DI system. 53333 * 53334 * NOTE: this function is an alias so that we can change the type of the function to have `void` 53335 * return type. 53336 */ 53337 53338 53339const leaveDI = leaveViewLight; 53340/** 53341 * Leave the current `LView` 53342 * 53343 * This pops the `LFrame` with the associated `LView` from the stack. 53344 * 53345 * IMPORTANT: We must zero out the `LFrame` values here otherwise they will be retained. This is 53346 * because for performance reasons we don't release `LFrame` but rather keep it for next use. 53347 */ 53348 53349function leaveView() { 53350 const oldLFrame = leaveViewLight(); 53351 oldLFrame.isParent = true; 53352 oldLFrame.tView = null; 53353 oldLFrame.selectedIndex = -1; 53354 oldLFrame.contextLView = null; 53355 oldLFrame.elementDepthCount = 0; 53356 oldLFrame.currentDirectiveIndex = -1; 53357 oldLFrame.currentNamespace = null; 53358 oldLFrame.bindingRootIndex = -1; 53359 oldLFrame.bindingIndex = -1; 53360 oldLFrame.currentQueryIndex = 0; 53361} 53362 53363function nextContextImpl(level) { 53364 const contextLView = instructionState.lFrame.contextLView = walkUpViews(level, instructionState.lFrame.contextLView); 53365 return contextLView[CONTEXT]; 53366} 53367 53368function walkUpViews(nestingLevel, currentView) { 53369 while (nestingLevel > 0) { 53370 ngDevMode && assertDefined(currentView[DECLARATION_VIEW], 'Declaration view should be defined if nesting level is greater than 0.'); 53371 currentView = currentView[DECLARATION_VIEW]; 53372 nestingLevel--; 53373 } 53374 53375 return currentView; 53376} 53377/** 53378 * Gets the currently selected element index. 53379 * 53380 * Used with {@link property} instruction (and more in the future) to identify the index in the 53381 * current `LView` to act on. 53382 */ 53383 53384 53385function getSelectedIndex() { 53386 return instructionState.lFrame.selectedIndex; 53387} 53388/** 53389 * Sets the most recent index passed to {@link select} 53390 * 53391 * Used with {@link property} instruction (and more in the future) to identify the index in the 53392 * current `LView` to act on. 53393 * 53394 * (Note that if an "exit function" was set earlier (via `setElementExitFn()`) then that will be 53395 * run if and when the provided `index` value is different from the current selected index value.) 53396 */ 53397 53398 53399function setSelectedIndex(index) { 53400 ngDevMode && index !== -1 && assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Index must be past HEADER_OFFSET (or -1).'); 53401 ngDevMode && assertLessThan(index, instructionState.lFrame.lView.length, 'Can\'t set index passed end of LView'); 53402 instructionState.lFrame.selectedIndex = index; 53403} 53404/** 53405 * Gets the `tNode` that represents currently selected element. 53406 */ 53407 53408 53409function getSelectedTNode() { 53410 const lFrame = instructionState.lFrame; 53411 return getTNode(lFrame.tView, lFrame.selectedIndex); 53412} 53413/** 53414 * Sets the namespace used to create elements to `'http://www.w3.org/2000/svg'` in global state. 53415 * 53416 * @codeGenApi 53417 */ 53418 53419 53420function ɵɵnamespaceSVG() { 53421 instructionState.lFrame.currentNamespace = SVG_NAMESPACE; 53422} 53423/** 53424 * Sets the namespace used to create elements to `'http://www.w3.org/1998/MathML/'` in global state. 53425 * 53426 * @codeGenApi 53427 */ 53428 53429 53430function ɵɵnamespaceMathML() { 53431 instructionState.lFrame.currentNamespace = MATH_ML_NAMESPACE; 53432} 53433/** 53434 * Sets the namespace used to create elements to `null`, which forces element creation to use 53435 * `createElement` rather than `createElementNS`. 53436 * 53437 * @codeGenApi 53438 */ 53439 53440 53441function ɵɵnamespaceHTML() { 53442 namespaceHTMLInternal(); 53443} 53444/** 53445 * Sets the namespace used to create elements to `null`, which forces element creation to use 53446 * `createElement` rather than `createElementNS`. 53447 */ 53448 53449 53450function namespaceHTMLInternal() { 53451 instructionState.lFrame.currentNamespace = null; 53452} 53453 53454function getNamespace$1() { 53455 return instructionState.lFrame.currentNamespace; 53456} 53457/** 53458 * @license 53459 * Copyright Google LLC All Rights Reserved. 53460 * 53461 * Use of this source code is governed by an MIT-style license that can be 53462 * found in the LICENSE file at https://angular.io/license 53463 */ 53464 53465/** 53466 * Adds all directive lifecycle hooks from the given `DirectiveDef` to the given `TView`. 53467 * 53468 * Must be run *only* on the first template pass. 53469 * 53470 * Sets up the pre-order hooks on the provided `tView`, 53471 * see {@link HookData}
53471 for details about the data structure. 53472 * 53473 * @param directiveIndex The index of the directive in LView 53474 * @param directiveDef The definition containing the hooks to setup in tView 53475 * @param tView The current TView 53476 */ 53477 53478 53479function registerPreOrderHooks(directiveIndex, directiveDef, tView) { 53480 ngDevMode && assertFirstCreatePass(tView); 53481 const { 53482 ngOnChanges, 53483 ngOnInit, 53484 ngDoCheck 53485 } = directiveDef.type.prototype; 53486 53487 if (ngOnChanges) { 53488 const wrappedOnChanges = NgOnChangesFeatureImpl(directiveDef); 53489 (tView.preOrderHooks || (tView.preOrderHooks = [])).push(directiveIndex, wrappedOnChanges); 53490 (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = [])).push(directiveIndex, wrappedOnChanges); 53491 } 53492 53493 if (ngOnInit) { 53494 (tView.preOrderHooks || (tView.preOrderHooks = [])).push(0 - directiveIndex, ngOnInit); 53495 } 53496 53497 if (ngDoCheck) { 53498 (tView.preOrderHooks || (tView.preOrderHooks = [])).push(directiveIndex, ngDoCheck); 53499 (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = [])).push(directiveIndex, ngDoCheck); 53500 } 53501} 53502/** 53503 * 53504 * Loops through the directives on the provided `tNode` and queues hooks to be 53505 * run that are not initialization hooks. 53506 * 53507 * Should be executed during `elementEnd()` and similar to 53508 * preserve hook execution order. Content, view, and destroy hooks for projected 53509 * components and directives must be called *before* their hosts. 53510 * 53511 * Sets up the content, view, and destroy hooks on the provided `tView`, 53512 * see {@link HookData} for details about the data structure. 53513 * 53514 * NOTE: This does not set up `onChanges`, `onInit` or `doCheck`, those are set up 53515 * separately at `elementStart`. 53516 * 53517 * @param tView The current TView 53518 * @param tNode The TNode whose directives are to be searched for hooks to queue 53519 */ 53520 53521 53522function registerPostOrderHooks(tView, tNode) { 53523 ngDevMode && assertFirstCreatePass(tView); // It's necessary to loop through the directives at elementEnd() (rather than processing in 53524 // directiveCreate) so we can preserve the current hook order. Content, view, and destroy 53525 // hooks for projected components and directives must be called *before* their hosts. 53526 53527 for (let i = tNode.directiveStart, end = tNode.directiveEnd; i < end; i++) { 53528 const directiveDef = tView.data[i]; 53529 ngDevMode && assertDefined(directiveDef, 'Expecting DirectiveDef'); 53530 const lifecycleHooks = directiveDef.type.prototype; 53531 const { 53532 ngAfterContentInit, 53533 ngAfterContentChecked, 53534 ngAfterViewInit, 53535 ngAfterViewChecked, 53536 ngOnDestroy 53537 } = lifecycleHooks; 53538 53539 if (ngAfterContentInit) { 53540 (tView.contentHooks || (tView.contentHooks = [])).push(-i, ngAfterContentInit); 53541 } 53542 53543 if (ngAfterContentChecked) { 53544 (tView.contentHooks || (tView.contentHooks = [])).push(i, ngAfterContentChecked); 53545 (tView.contentCheckHooks || (tView.contentCheckHooks = [])).push(i, ngAfterContentChecked); 53546 } 53547 53548 if (ngAfterViewInit) { 53549 (tView.viewHooks || (tView.viewHooks = [])).push(-i, ngAfterViewInit); 53550 } 53551 53552 if (ngAfterViewChecked) { 53553 (tView.viewHooks || (tView.viewHooks = [])).push(i, ngAfterViewChecked); 53554 (tView.viewCheckHooks || (tView.viewCheckHooks = [])).push(i, ngAfterViewChecked); 53555 } 53556 53557 if (ngOnDestroy != null) { 53558 (tView.destroyHooks || (tView.destroyHooks = [])).push(i, ngOnDestroy); 53559 } 53560 } 53561} 53562/** 53563 * Executing hooks requires complex logic as we need to deal with 2 constraints. 53564 * 53565 * 1. Init hooks (ngOnInit, ngAfterContentInit, ngAfterViewInit) must all be executed once and only 53566 * once, across many change detection cycles. This must be true even if some hooks throw, or if 53567 * some recursively trigger a change detection cycle. 53568 * To solve that, it is required to track the state of the execution of these init hooks. 53569 * This is done by storing and maintaining flags in the view: the {@link InitPhaseState}, 53570 * and the index within that phase. They can be seen as a cursor in the following structure: 53571 * [[onInit1, onInit2], [afterContentInit1], [afterViewInit1, afterViewInit2, afterViewInit3]] 53572 * They are are stored as flags in LView[FLAGS]. 53573 * 53574 * 2. Pre-order hooks can be executed in batches, because of the select instruction. 53575 * To be able to pause and resume their execution, we also need some state about the hook's array 53576 * that is being processed: 53577 * - the index of the next hook to be executed 53578 * - the number of init hooks already found in the processed part of the array 53579 * They are are stored as flags in LView[PREORDER_HOOK_FLAGS]. 53580 */ 53581 53582/** 53583 * Executes pre-order check hooks ( OnChanges, DoChanges) given a view where all the init hooks were 53584 * executed once. This is a light version of executeInitAndCheckPreOrderHooks where we can skip read 53585 * / write of the init-hooks related flags. 53586 * @param lView The LView where hooks are defined 53587 * @param hooks Hooks to be run
53588 * @param nodeIndex 3 cases depending on the value: 53589 * - undefined: all hooks from the array should be executed (post-order case) 53590 * - null: execute hooks only from the saved index until the end of the array (pre-order case, when 53591 * flushing the remaining hooks) 53592 * - number: execute hooks only from the saved index until that node index exclusive (pre-order 53593 * case, when executing select(number)) 53594 */ 53595 53596 53597function executeCheckHooks(lView, hooks, nodeIndex) { 53598 callHooks(lView, hooks, 3 53599 /* InitPhaseState.InitPhaseCompleted */ 53600 , nodeIndex); 53601} 53602/** 53603 * Executes post-order init and check hooks (one of AfterContentInit, AfterContentChecked, 53604 * AfterViewInit, AfterViewChecked) given a view where there are pending init hooks to be executed. 53605 * @param lView The LView where hooks are defined 53606 * @param hooks Hooks to be run 53607 * @param initPhase A phase for which hooks should be run 53608 * @param nodeIndex 3 cases depending on the value: 53609 * - undefined: all hooks from the array should be executed (post-order case) 53610 * - null: execute hooks only from the saved index until the end of the array (pre-order case, when 53611 * flushing the remaining hooks) 53612 * - number: execute hooks only from the saved index until that node index exclusive (pre-order 53613 * case, when executing select(number)) 53614 */ 53615 53616 53617function executeInitAndCheckHooks(lView, hooks, initPhase, nodeIndex) { 53618 ngDevMode && assertNotEqual(initPhase, 3 53619 /* InitPhaseState.InitPhaseCompleted */ 53620 , 'Init pre-order hooks should not be called more than once'); 53621 53622 if ((lView[FLAGS] & 3 53623 /* LViewFlags.InitPhaseStateMask */ 53624 ) === initPhase) { 53625 callHooks(lView, hooks, initPhase, nodeIndex); 53626 } 53627} 53628 53629function incrementInitPhaseFlags(lView, initPhase) { 53630 ngDevMode && assertNotEqual(initPhase, 3 53631 /* InitPhaseState.InitPhaseCompleted */ 53632 , 'Init hooks phase should not be incremented after all init hooks have been run.'); 53633 let flags = lView[FLAGS]; 53634 53635 if ((flags & 3 53636 /* LViewFlags.InitPhaseStateMask */ 53637 ) === initPhase) { 53638 flags &= 2047 53639 /* LViewFlags.IndexWithinInitPhaseReset */ 53640 ; 53641 flags += 1 53642 /* LViewFlags.InitPhaseStateIncrementer */ 53643 ; 53644 lView[FLAGS] = flags; 53645 } 53646} 53647/** 53648 * Calls lifecycle hooks with their contexts, skipping init hooks if it's not 53649 * the first LView pass 53650 * 53651 * @param currentView The current view 53652 * @param arr The array in which the hooks are found 53653 * @param initPhaseState the current state of the init phase 53654 * @param currentNodeIndex 3 cases depending on the value: 53655 * - undefined: all hooks from the array should be executed (post-order case) 53656 * - null: execute hooks only from the saved index until the end of the array (pre-order case, when 53657 * flushing the remaining hooks) 53658 * - number: execute hooks only from the saved index until that node index exclusive (pre-order 53659 * case, when executing select(number)) 53660 */ 53661 53662 53663function callHooks(currentView, arr, initPhase, currentNodeIndex) { 53664 ngDevMode && assertEqual(isInCheckNoChangesMode(), false, 'Hooks should never be run when in check no changes mode.'); 53665 const startIndex = currentNodeIndex !== undefined ? currentView[PREORDER_HOOK_FLAGS] & 65535 53666 /* PreOrderHookFlags.IndexOfTheNextPreOrderHookMaskMask */ 53667 : 0; 53668 const nodeIndexLimit = currentNodeIndex != null ? currentNodeIndex : -1; 53669 const max = arr.length - 1; // Stop the loop at length - 1, because we look for the hook at i + 1 53670 53671 let lastNodeIndexFound = 0; 53672 53673 for (let i = startIndex; i < max; i++) { 53674 const hook = arr[i + 1]; 53675 53676 if (typeof hook === 'number') { 53677 lastNodeIndexFound = arr[i]; 53678 53679 if (currentNodeIndex != null && lastNodeIndexFound >= currentNodeIndex) { 53680 break; 53681 } 53682 } else { 53683 const isInitHook = arr[i] < 0; 53684 if (isInitHook) currentView[PREORDER_HOOK_FLAGS] += 65536 53685 /* PreOrderHookFlags.NumberOfInitHooksCalledIncrementer */ 53686 ; 53687 53688 if (lastNodeIndexFound < nodeIndexLimit || nodeIndexLimit == -1) { 53689 callHook(currentView, initPhase, arr, i); 53690 currentView[PREORDER_HOOK_FLAGS] = (currentView[PREORDER_HOOK_FLAGS] & 4294901760 53691 /* PreOrderHookFlags.NumberOfInitHooksCalledMask */ 53692 ) + i + 2; 53693 } 53694 53695 i++; 53696 } 53697 } 53698} 53699/** 53700 * Execute one hook against the current `LView`. 53701 * 53702 * @param currentView The current view 53703 * @param initPhaseState the current state of the init phase 53704 * @param arr The array in which the hooks are found 53705 * @param i The current index within the hook data array 53706 */ 53707 53708 53709function callHook(currentView, initPhase, arr, i) { 53710 const isInitHook = arr[i] < 0; 53711 const hook = arr[i + 1];
53712 const directiveIndex = isInitHook ? -arr[i] : arr[i]; 53713 const directive = currentView[directiveIndex]; 53714 53715 if (isInitHook) { 53716 const indexWithintInitPhase = currentView[FLAGS] >> 11 53717 /* LViewFlags.IndexWithinInitPhaseShift */ 53718 ; // The init phase state must be always checked here as it may have been recursively updated. 53719 53720 if (indexWithintInitPhase < currentView[PREORDER_HOOK_FLAGS] >> 16 53721 /* PreOrderHookFlags.NumberOfInitHooksCalledShift */ 53722 && (currentView[FLAGS] & 3 53723 /* LViewFlags.InitPhaseStateMask */ 53724 ) === initPhase) { 53725 currentView[FLAGS] += 2048 53726 /* LViewFlags.IndexWithinInitPhaseIncrementer */ 53727 ; 53728 profiler(4 53729 /* ProfilerEvent.LifecycleHookStart */ 53730 , directive, hook); 53731 53732 try { 53733 hook.call(directive); 53734 } finally { 53735 profiler(5 53736 /* ProfilerEvent.LifecycleHookEnd */ 53737 , directive, hook); 53738 } 53739 } 53740 } else { 53741 profiler(4 53742 /* ProfilerEvent.LifecycleHookStart */ 53743 , directive, hook); 53744 53745 try { 53746 hook.call(directive); 53747 } finally { 53748 profiler(5 53749 /* ProfilerEvent.LifecycleHookEnd */ 53750 , directive, hook); 53751 } 53752 } 53753} 53754/** 53755 * @license 53756 * Copyright Google LLC All Rights Reserved. 53757 * 53758 * Use of this source code is governed by an MIT-style license that can be 53759 * found in the LICENSE file at https://angular.io/license 53760 */ 53761 53762 53763const NO_PARENT_INJECTOR = -1; 53764/** 53765 * Each injector is saved in 9 contiguous slots in `LView` and 9 contiguous slots in 53766 * `TView.data`. This allows us to store information about the current node's tokens (which 53767 * can be shared in `TView`) as well as the tokens of its ancestor nodes (which cannot be 53768 * shared, so they live in `LView`). 53769 * 53770 * Each of these slots (aside from the last slot) contains a bloom filter. This bloom filter 53771 * determines whether a directive is available on the associated node or not. This prevents us 53772 * from searching the directives array at this level unless it's probable the directive is in it. 53773 * 53774 * See: https://en.wikipedia.org/wiki/Bloom_filter for more about bloom filters. 53775 * 53776 * Because all injectors have been flattened into `LView` and `TViewData`, they cannot typed 53777 * using interfaces as they were previously. The start index of each `LInjector` and `TInjector` 53778 * will differ based on where it is flattened into the main array, so it's not possible to know 53779 * the indices ahead of time and save their types here. The interfaces are still included here 53780 * for documentation purposes. 53781 * 53782 * export interface LInjector extends Array<any> { 53783 * 53784 * // Cumulative bloom for directive IDs 0-31 (IDs are % BLOOM_SIZE) 53785 * [0]: number; 53786 * 53787 * // Cumulative bloom for directive IDs 32-63 53788 * [1]: number; 53789 * 53790 * // Cumulative bloom for directive IDs 64-95 53791 * [2]: number; 53792 * 53793 * // Cumulative bloom for directive IDs 96-127 53794 * [3]: number; 53795 * 53796 * // Cumulative bloom for directive IDs 128-159 53797 * [4]: number; 53798 * 53799 * // Cumulative bloom for directive IDs 160 - 191 53800 * [5]: number; 53801 * 53802 * // Cumulative bloom for directive IDs 192 - 223 53803 * [6]: number; 53804 * 53805 * // Cumulative bloom for directive IDs 224 - 255 53806 * [7]: number; 53807 * 53808 * // We need to store a reference to the injector's parent so DI can keep looking up 53809 * // the injector tree until it finds the dependency it's looking for. 53810 * [PARENT_INJECTOR]: number; 53811 * } 53812 * 53813 * export interface TInjector extends Array<any> { 53814 * 53815 * // Shared node bloom for directive IDs 0-31 (IDs are % BLOOM_SIZE) 53816 * [0]: number; 53817 * 53818 * // Shared node bloom for directive IDs 32-63 53819 * [1]: number; 53820 * 53821 * // Shared node bloom for directive IDs 64-95 53822 * [2]: number; 53823 * 53824 * // Shared node bloom for directive IDs 96-127 53825 * [3]: number; 53826 * 53827 * // Shared node bloom for directive IDs 128-159 53828 * [4]: number; 53829 * 53830 * // Shared node bloom for directive IDs 160 - 191 53831 * [5]: number; 53832 * 53833 * // Shared node bloom for directive IDs 192 - 223 53834 * [6]: number; 53835 * 53836 * // Shared node bloom for directive IDs 224 - 255 53837 * [7]: number; 53838 * 53839 * // Necessary to find directive indices for a particular node. 53840 * [TNODE]: TElementNode|TElementContainerNode|TContainerNode; 53841 * } 53842 */ 53843 53844/** 53845 * Factory for creating instances of injectors in the NodeInjector. 53846 * 53847 * This factory is complicated by the fact that it can resolve `multi` factories as well. 53848 * 53849 * NOTE: Some of the fields are optional which means that this class has two hidden classes. 53850 * - One without `multi` support (most common) 53851 * - One with `multi` values, (rare). 53852 * 53853 * Since VMs can cache up to 4 inline hidden classes this is OK. 53854 * 53855 * - Single factory: Only `resolving` and `factory` is defined.
53856 * - `providers` factory: `componentProviders` is a number and `index = -1`. 53857 * - `viewProviders` factory: `componentProviders` is a number and `index` points to `providers`. 53858 */ 53859 53860class NodeInjectorFactory { 53861 constructor( 53862 /** 53863 * Factory to invoke in order to create a new instance. 53864 */ 53865 factory, 53866 /** 53867 * Set to `true` if the token is declared in `viewProviders` (or if it is component). 53868 */ 53869 isViewProvider, injectImplementation) { 53870 this.factory = factory; 53871 /** 53872 * Marker set to true during factory invocation to see if we get into recursive loop. 53873 * Recursive loop causes an error to be displayed. 53874 */ 53875 53876 this.resolving = false; 53877 ngDevMode && assertDefined(factory, 'Factory not specified'); 53878 ngDevMode && assertEqual(typeof factory, 'function', 'Expected factory function.'); 53879 this.canSeeViewProviders = isViewProvider; 53880 this.injectImpl = injectImplementation; 53881 } 53882 53883} 53884 53885function isFactory(obj) { 53886 return obj instanceof NodeInjectorFactory; 53887} // Note: This hack is necessary so we don't erroneously get a circular dependency 53888// failure based on types. 53889 53890 53891const unusedValueExportToPlacateAjd$6 = 1; 53892/** 53893 * Converts `TNodeType` into human readable text. 53894 * Make sure this matches with `TNodeType` 53895 */ 53896 53897function toTNodeTypeAsString(tNodeType) { 53898 let text = ''; 53899 tNodeType & 1 53900 /* TNodeType.Text */ 53901 && (text += '|Text'); 53902 tNodeType & 2 53903 /* TNodeType.Element */ 53904 && (text += '|Element'); 53905 tNodeType & 4 53906 /* TNodeType.Container */ 53907 && (text += '|Container'); 53908 tNodeType & 8 53909 /* TNodeType.ElementContainer */ 53910 && (text += '|ElementContainer'); 53911 tNodeType & 16 53912 /* TNodeType.Projection */ 53913 && (text += '|Projection'); 53914 tNodeType & 32 53915 /* TNodeType.Icu */ 53916 && (text += '|IcuContainer'); 53917 tNodeType & 64 53918 /* TNodeType.Placeholder */ 53919 && (text += '|Placeholder'); 53920 return text.length > 0 ? text.substring(1) : text; 53921} // Note: This hack is necessary so we don't erroneously get a circular dependency 53922// failure based on types. 53923 53924 53925const unusedValueExportToPlacateAjd$5 = 1; 53926/** 53927 * Returns `true` if the `TNode` has a directive which has `@Input()` for `class` binding. 53928 * 53929 * ``` 53930 * <div my-dir [class]="exp"></div> 53931 * ``` 53932 * and 53933 * ``` 53934 * @Directive({ 53935 * }) 53936 * class MyDirective { 53937 * @Input() 53938 * class: string; 53939 * } 53940 * ``` 53941 * 53942 * In the above case it is necessary to write the reconciled styling information into the 53943 * directive's input. 53944 * 53945 * @param tNode 53946 */ 53947 53948function hasClassInput(tNode) { 53949 return (tNode.flags & 16 53950 /* TNodeFlags.hasClassInput */ 53951 ) !== 0; 53952} 53953/** 53954 * Returns `true` if the `TNode` has a directive which has `@Input()` for `style` binding. 53955 * 53956 * ``` 53957 * <div my-dir [style]="exp"></div> 53958 * ``` 53959 * and 53960 * ``` 53961 * @Directive({ 53962 * }) 53963 * class MyDirective { 53964 * @Input() 53965 * class: string; 53966 * } 53967 * ``` 53968 * 53969 * In the above case it is necessary to write the reconciled styling information into the 53970 * directive's input. 53971 * 53972 * @param tNode 53973 */ 53974 53975 53976function hasStyleInput(tNode) { 53977 return (tNode.flags & 32 53978 /* TNodeFlags.hasStyleInput */ 53979 ) !== 0; 53980} 53981/** 53982 * @license 53983 * Copyright Google LLC All Rights Reserved. 53984 * 53985 * Use of this source code is governed by an MIT-style license that can be 53986 * found in the LICENSE file at https://angular.io/license 53987 */ 53988 53989 53990function assertTNodeType(tNode, expectedTypes, message) { 53991 assertDefined(tNode, 'should be called with a TNode'); 53992 53993 if ((tNode.type & expectedTypes) === 0) { 53994 throwError(message || `Expected [${toTNodeTypeAsString(expectedTypes)}] but got ${toTNodeTypeAsString(tNode.type)}.`); 53995 } 53996} 53997 53998function assertPureTNodeType(type) { 53999 if (!(type === 2 54000 /* TNodeType.Element */ 54001 || // 54002 type === 1 54003 /* TNodeType.Text */ 54004 || // 54005 type === 4 54006 /* TNodeType.Container */ 54007 || // 54008 type === 8 54009 /* TNodeType.ElementContainer */ 54010 || // 54011 type === 32 54012 /* TNodeType.Icu */ 54013 || // 54014 type === 16 54015 /* TNodeType.Projection */ 54016 || // 54017 type === 64 54018 /* TNodeType.Placeholder */ 54019 )) { 54020 throwError(`Expected TNodeType to have only a single type selected, but got ${toTNodeTypeAsString(type)}.`); 54021 } 54022} 54023/** 54024 * Assigns all attribute values to the provided element via the inferred renderer. 54025 * 54026 * This function accepts two forms of attribute entries: 54027 * 54028 * default: (key, value): 54029 * attrs = [key1, value1, key2, value2] 54030 * 54031 * namespaced: (NAMESPACE_MARKER, uri, name, value) 54032 * attrs = [NAMESPACE_MARKER, uri, name, value, NAMESPACE_MARKER, uri, name, value] 54033 * 54034 * The `attrs` array can contain a mix of both the default and namespaced entries. 54035 * The "default" values are set without a marker, but if the function comes across 54036 * a marker value then it will attempt to set a namespaced value. If the marker is 54037 * not of a namespaced value then the function will quit and return the index value 54038 * where it stopped during the iteration of the attrs array. 54039 * 54040 * See [AttributeMarker] to understand what the namespace marker value is. 54041 *
vendor: 46,980 bytes, lines 54042-55360
54042 * Note that this instruction does not support assigning style and class values to 54043 * an element. See `elementStart` and `elementHostAttrs` to learn how styling values 54044 * are applied to an element. 54045 * @param renderer The renderer to be used 54046 * @param native The element that the attributes will be assigned to 54047 * @param attrs The attribute array of values that will be assigned to the element 54048 * @returns the index value that was last accessed in the attributes array 54049 */ 54050 54051 54052function setUpAttributes(renderer, native, attrs) { 54053 let i = 0; 54054 54055 while (i < attrs.length) { 54056 const value = attrs[i]; 54057 54058 if (typeof value === 'number') { 54059 // only namespaces are supported. Other value types (such as style/class 54060 // entries) are not supported in this function. 54061 if (value !== 0 54062 /* AttributeMarker.NamespaceURI */ 54063 ) { 54064 break; 54065 } // we just landed on the marker value ... therefore 54066 // we should skip to the next entry 54067 54068 54069 i++; 54070 const namespaceURI = attrs[i++]; 54071 const attrName = attrs[i++]; 54072 const attrVal = attrs[i++]; 54073 ngDevMode && ngDevMode.rendererSetAttribute++; 54074 renderer.setAttribute(native, attrName, attrVal, namespaceURI); 54075 } else { 54076 // attrName is string; 54077 const attrName = value; 54078 const attrVal = attrs[++i]; // Standard attributes 54079 54080 ngDevMode && ngDevMode.rendererSetAttribute++; 54081 54082 if (isAnimationProp(attrName)) { 54083 renderer.setProperty(native, attrName, attrVal); 54084 } else { 54085 renderer.setAttribute(native, attrName, attrVal); 54086 } 54087 54088 i++; 54089 } 54090 } // another piece of code may iterate over the same attributes array. Therefore 54091 // it may be helpful to return the exact spot where the attributes array exited 54092 // whether by running into an unsupported marker or if all the static values were 54093 // iterated over. 54094 54095 54096 return i; 54097} 54098/** 54099 * Test whether the given value is a marker that indicates that the following 54100 * attribute values in a `TAttributes` array are only the names of attributes, 54101 * and not name-value pairs. 54102 * @param marker The attribute marker to test. 54103 * @returns true if the marker is a "name-only" marker (e.g. `Bindings`, `Template` or `I18n`). 54104 */ 54105 54106 54107function isNameOnlyAttributeMarker(marker) { 54108 return marker === 3 54109 /* AttributeMarker.Bindings */ 54110 || marker === 4 54111 /* AttributeMarker.Template */ 54112 || marker === 6 54113 /* AttributeMarker.I18n */ 54114 ; 54115} 54116 54117function isAnimationProp(name) { 54118 // Perf note: accessing charCodeAt to check for the first character of a string is faster as 54119 // compared to accessing a character at index 0 (ex. name[0]). The main reason for this is that 54120 // charCodeAt doesn't allocate memory to return a substring. 54121 return name.charCodeAt(0) === 64 54122 /* CharCode.AT_SIGN */ 54123 ; 54124} 54125/** 54126 * Merges `src` `TAttributes` into `dst` `TAttributes` removing any duplicates in the process. 54127 * 54128 * This merge function keeps the order of attrs same. 54129 * 54130 * @param dst Location of where the merged `TAttributes` should end up. 54131 * @param src `TAttributes` which should be appended to `dst` 54132 */ 54133 54134 54135function mergeHostAttrs(dst, src) { 54136 if (src === null || src.length === 0) {// do nothing 54137 } else if (dst === null || dst.length === 0) { 54138 // We have source, but dst is empty, just make a copy. 54139 dst = src.slice(); 54140 } else { 54141 let srcMarker = -1 54142 /* AttributeMarker.ImplicitAttributes */ 54143 ; 54144 54145 for (let i = 0; i < src.length; i++) { 54146 const item = src[i]; 54147 54148 if (typeof item === 'number') { 54149 srcMarker = item; 54150 } else { 54151 if (srcMarker === 0 54152 /* AttributeMarker.NamespaceURI */ 54153 ) {// Case where we need to consume `key1`, `key2`, `value` items. 54154 } else if (srcMarker === -1 54155 /* AttributeMarker.ImplicitAttributes */ 54156 || srcMarker === 2 54157 /* AttributeMarker.Styles */ 54158 ) { 54159 // Case where we have to consume `key1` and `value` only. 54160 mergeHostAttribute(dst, srcMarker, item, null, src[++i]); 54161 } else { 54162 // Case where we have to consume `key1` only. 54163 mergeHostAttribute(dst, srcMarker, item, null, null); 54164 } 54165 } 54166 } 54167 } 54168 54169 return dst; 54170} 54171/** 54172 * Append `key`/`value` to existing `TAttributes` taking region marker and duplicates into account. 54173 * 54174 * @param dst `TAttributes` to append to. 54175 * @param marker Region where the `key`/`value` should be added. 54176 * @param key1 Key to add to `TAttributes` 54177 * @param key2 Key to add to `TAttributes` (in case of `AttributeMarker.NamespaceURI`) 54178 * @param value Value to add or to overwrite to `TAttributes` Only used if `marker` is not Class. 54179 */ 54180 54181 54182function mergeHostAttribute(dst, marker, key1, key2, value) { 54183 let i = 0; // Assume that new markers will be inserted at the end. 54184 54185 let markerInsertPosition = dst.length; // scan until correct type. 54186 54187 if (marker === -1 54188 /* AttributeMarker.ImplicitAttributes */ 54189 ) { 54190 markerInsertPosition = -1; 54191 } else { 54192 while (i < dst.length) { 54193 const dstValue = dst[i++]; 54194 54195 if (typeof dstValue === 'number') { 54196 if (dstValue === marker) { 54197 markerInsertPosition = -1; 54198 break; 54199 } else if (dstValue > marker) { 54200 // We need to save this as we want the markers to be inserted in specific order. 54201 markerInsertPosition = i - 1; 54202 break; 54203 } 54204 } 54205 } 54206 } // search until you find place of insertion 54207 54208 54209 while (i < dst.length) { 54210 const item = dst[i]; 54211 54212 if (typeof item === 'number') { 54213 // since `i` started as the index after the marker, we did not find it if we are at the next 54214 // marker 54215 break; 54216 } else if (item === key1) { 54217 // We already have same token 54218 if (key2 === null) { 54219 if (value !== null) { 54220 dst[i + 1] = value; 54221 } 54222 54223 return; 54224 } else if (key2 === dst[i + 1]) { 54225 dst[i + 2] = value; 54226 return; 54227 } 54228 } // Increment counter. 54229 54230 54231 i++; 54232 if (key2 !== null) i++; 54233 if (value !== null) i++; 54234 } // insert at location. 54235 54236 54237 if (markerInsertPosition !== -1) { 54238 dst.splice(markerInsertPosition, 0, marker); 54239 i = markerInsertPosition + 1; 54240 } 54241 54242 dst.splice(i++, 0, key1); 54243 54244 if (key2 !== null) { 54245 dst.splice(i++, 0, key2); 54246 } 54247 54248 if (value !== null) { 54249 dst.splice(i++, 0, value); 54250 } 54251} 54252/** 54253 * @license 54254 * Copyright Google LLC All Rights Reserved. 54255 * 54256 * Use of this source code is governed by an MIT-style license that can be 54257 * found in the LICENSE file at https://angular.io/license 54258 */ 54259/// Parent Injector Utils /////////////////////////////////////////////////////////////// 54260 54261 54262function hasParentInjector(parentLocation) { 54263 return parentLocation !== NO_PARENT_INJECTOR; 54264} 54265 54266function getParentInjectorIndex(parentLocation) { 54267 ngDevMode && assertNumber(parentLocation, 'Number expected'); 54268 ngDevMode && assertNotEqual(parentLocation, -1, 'Not a valid state.'); 54269 const parentInjectorIndex = parentLocation & 32767 54270 /* RelativeInjectorLocationFlags.InjectorIndexMask */ 54271 ; 54272 ngDevMode && assertGreaterThan(parentInjectorIndex, HEADER_OFFSET, 'Parent injector must be pointing past HEADER_OFFSET.'); 54273 return parentLocation & 32767 54274 /* RelativeInjectorLocationFlags.InjectorIndexMask */ 54275 ; 54276} 54277 54278function getParentInjectorViewOffset(parentLocation) { 54279 return parentLocation >> 16 54280 /* RelativeInjectorLocationFlags.ViewOffsetShift */ 54281 ; 54282} 54283/** 54284 * Unwraps a parent injector location number to find the view offset from the current injector, 54285 * then walks up the declaration view tree until the view is found that contains the parent 54286 * injector. 54287 * 54288 * @param location The location of the parent injector, which contains the view offset 54289 * @param startView The LView instance from which to start walking up the view tree 54290 * @returns The LView instance that contains the parent injector 54291 */ 54292 54293 54294function getParentInjectorView(location, startView) { 54295 let viewOffset = getParentInjectorViewOffset(location); 54296 let parentView = startView; // For most cases, the parent injector can be found on the host node (e.g. for component 54297 // or container), but we must keep the loop here to support the rarer case of deeply nested 54298 // <ng-template> tags or inline views, where the parent injector might live many views 54299 // above the child injector. 54300 54301 while (viewOffset > 0) { 54302 parentView = parentView[DECLARATION_VIEW]; 54303 viewOffset--; 54304 } 54305 54306 return parentView; 54307} 54308/** 54309 * @license 54310 * Copyright Google LLC All Rights Reserved. 54311 * 54312 * Use of this source code is governed by an MIT-style license that can be 54313 * found in the LICENSE file at https://angular.io/license 54314 */ 54315 54316/** 54317 * Defines if the call to `inject` should include `viewProviders` in its resolution. 54318 * 54319 * This is set to true when we try to instantiate a component. This value is reset in 54320 * `getNodeInjectable` to a value which matches the declaration location of the token about to be 54321 * instantiated. This is done so that if we are injecting a token which was declared outside of 54322 * `viewProviders` we don't accidentally pull `viewProviders` in. 54323 * 54324 * Example: 54325 * 54326 * ``` 54327 * @Injectable() 54328 * class MyService { 54329 * constructor(public value: String) {} 54330 * } 54331 * 54332 * @Component({ 54333 * providers: [ 54334 * MyService, 54335 * {provide: String, value: 'providers' } 54336 * ] 54337 * viewProviders: [ 54338 * {provide: String, value: 'viewProviders'} 54339 * ] 54340 * }) 54341 * class MyComponent { 54342 * constructor(myService: MyService, value: String) { 54343 * // We expect that Component can see into `viewProviders`. 54344 * expect(value).toEqual('viewProviders'); 54345 * // `MyService` was not declared in `viewProviders` hence it can't see it. 54346 * expect(myService.value).toEqual('providers'); 54347 * } 54348 * } 54349 * 54350 * ``` 54351 */ 54352 54353 54354let includeViewProviders = true; 54355 54356function setIncludeViewProviders(v) { 54357 const oldValue = includeViewProviders; 54358 includeViewProviders = v; 54359 return oldValue; 54360} 54361/** 54362 * The number of slots in each bloom filter (used by DI). The larger this number, the fewer 54363 * directives that will share slots, and thus, the fewer false positives when checking for 54364 * the existence of a directive. 54365 */ 54366 54367 54368const BLOOM_SIZE = 256; 54369const BLOOM_MASK = BLOOM_SIZE - 1; 54370/** 54371 * The number of bits that is represented by a single bloom bucket. JS bit operations are 32 bits, 54372 * so each bucket represents 32 distinct tokens which accounts for log2(32) = 5 bits of a bloom hash 54373 * number. 54374 */ 54375 54376const BLOOM_BUCKET_BITS = 5; 54377/** Counter used to generate unique IDs for directives. */ 54378 54379let nextNgElementId = 0; 54380/** Value used when something wasn't found by an injector. */ 54381 54382const NOT_FOUND = {}; 54383/** 54384 * Registers this directive as present in its node's injector by flipping the directive's 54385 * corresponding bit in the injector's bloom filter. 54386 * 54387 * @param injectorIndex The index of the node injector where this token should be registered 54388 * @param tView The TView for the injector's bloom filters 54389 * @param type The directive token to register 54390 */ 54391 54392function bloomAdd(injectorIndex, tView, type) { 54393 ngDevMode && assertEqual(tView.firstCreatePass, true, 'expected firstCreatePass to be true'); 54394 let id; 54395 54396 if (typeof type === 'string') { 54397 id = type.charCodeAt(0) || 0; 54398 } else if (type.hasOwnProperty(NG_ELEMENT_ID)) { 54399 id = type[NG_ELEMENT_ID]; 54400 } // Set a unique ID on the directive type, so if something tries to inject the directive, 54401 // we can easily retrieve the ID and hash it into the bloom bit that should be checked. 54402 54403 54404 if (id == null) { 54405 id = type[NG_ELEMENT_ID] = nextNgElementId++; 54406 } // We only have BLOOM_SIZE (256) slots in our bloom filter (8 buckets * 32 bits each), 54407 // so all unique IDs must be modulo-ed into a number from 0 - 255 to fit into the filter. 54408 54409 54410 const bloomHash = id & BLOOM_MASK; // Create a mask that targets the specific bit associated with the directive. 54411 // JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding 54412 // to bit positions 0 - 31 in a 32 bit integer. 54413 54414 const mask = 1 << bloomHash; // Each bloom bucket in `tData` represents `BLOOM_BUCKET_BITS` number of bits of `bloomHash`. 54415 // Any bits in `bloomHash` beyond `BLOOM_BUCKET_BITS` indicate the bucket offset that the mask 54416 // should be written to. 54417 54418 tView.data[injectorIndex + (bloomHash >> BLOOM_BUCKET_BITS)] |= mask; 54419} 54420/** 54421 * Creates (or gets an existing) injector for a given element or container. 54422 * 54423 * @param tNode for which an injector should be retrieved / created. 54424 * @param lView View where the node is stored 54425 * @returns Node injector 54426 */ 54427 54428 54429function getOrCreateNodeInjectorForNode(tNode, lView) { 54430 const existingInjectorIndex = getInjectorIndex(tNode, lView); 54431 54432 if (existingInjectorIndex !== -1) { 54433 return existingInjectorIndex; 54434 } 54435 54436 const tView = lView[TVIEW]; 54437 54438 if (tView.firstCreatePass) { 54439 tNode.injectorIndex = lView.length; 54440 insertBloom(tView.data, tNode); // foundation for node bloom 54441 54442 insertBloom(lView, null); // foundation for cumulative bloom 54443 54444 insertBloom(tView.blueprint, null); 54445 } 54446 54447 const parentLoc = getParentInjectorLocation(tNode, lView); 54448 const injectorIndex = tNode.injectorIndex; // If a parent injector can't be found, its location is set to -1. 54449 // In that case, we don't need to set up a cumulative bloom 54450 54451 if (hasParentInjector(parentLoc)) { 54452 const parentIndex = getParentInjectorIndex(parentLoc); 54453 const parentLView = getParentInjectorView(parentLoc, lView); 54454 const parentData = parentLView[TVIEW].data; // Creates a cumulative bloom filter that merges the parent's bloom filter 54455 // and its own cumulative bloom (which contains tokens for all ancestors) 54456 54457 for (let i = 0; i < 8 54458 /* NodeInjectorOffset.BLOOM_SIZE */ 54459 ; i++) { 54460 lView[injectorIndex + i] = parentLView[parentIndex + i] | parentData[parentIndex + i]; 54461 } 54462 } 54463 54464 lView[injectorIndex + 8 54465 /* NodeInjectorOffset.PARENT */ 54466 ] = parentLoc; 54467 return injectorIndex; 54468} 54469 54470function insertBloom(arr, footer) { 54471 arr.push(0, 0, 0, 0, 0, 0, 0, 0, footer); 54472} 54473 54474function getInjectorIndex(tNode, lView) { 54475 if (tNode.injectorIndex === -1 || // If the injector index is the same as its parent's injector index, then the index has been 54476 // copied down from the parent node. No injector has been created yet on this node. 54477 tNode.parent && tNode.parent.injectorIndex === tNode.injectorIndex || // After the first template pass, the injector index might exist but the parent values 54478 // might not have been calculated yet for this instance 54479 lView[tNode.injectorIndex + 8 54480 /* NodeInjectorOffset.PARENT */ 54481 ] === null) { 54482 return -1; 54483 } else { 54484 ngDevMode && assertIndexInRange(lView, tNode.injectorIndex); 54485 return tNode.injectorIndex; 54486 } 54487} 54488/** 54489 * Finds the index of the parent injector, with a view offset if applicable. Used to set the 54490 * parent injector initially. 54491 * 54492 * @returns Returns a number that is the combination of the number of LViews that we have to go up 54493 * to find the LView containing the parent inject AND the index of the injector within that LView. 54494 */ 54495 54496 54497function getParentInjectorLocation(tNode, lView) { 54498 if (tNode.parent && tNode.parent.injectorIndex !== -1) { 54499 // If we have a parent `TNode` and there is an injector associated with it we are done, because 54500 // the parent injector is within the current `LView`. 54501 return tNode.parent.injectorIndex; // ViewOffset is 0 54502 } // When parent injector location is computed it may be outside of the current view. (ie it could 54503 // be pointing to a declared parent location). This variable stores number of declaration parents 54504 // we need to walk up in order to find the parent injector location. 54505 54506 54507 let declarationViewOffset = 0; 54508 let parentTNode = null; 54509 let lViewCursor = lView; // The parent injector is not in the current `LView`. We will have to walk the declared parent 54510 // `LView` hierarchy and look for it. If we walk of the top, that means that there is no parent 54511 // `NodeInjector`. 54512 54513 while (lViewCursor !== null) { 54514 parentTNode = getTNodeFromLView(lViewCursor); 54515 54516 if (parentTNode === null) { 54517 // If we have no parent, than we are done. 54518 return NO_PARENT_INJECTOR; 54519 } 54520 54521 ngDevMode && parentTNode && assertTNodeForLView(parentTNode, lViewCursor[DECLARATION_VIEW]); // Every iteration of the loop requires that we go to the declared parent. 54522 54523 declarationViewOffset++; 54524 lViewCursor = lViewCursor[DECLARATION_VIEW]; 54525 54526 if (parentTNode.injectorIndex !== -1) { 54527 // We found a NodeInjector which points to something. 54528 return parentTNode.injectorIndex | declarationViewOffset << 16 54529 /* RelativeInjectorLocationFlags.ViewOffsetShift */ 54530 ; 54531 } 54532 } 54533 54534 return NO_PARENT_INJECTOR; 54535} 54536/** 54537 * Makes a type or an injection token public to the DI system by adding it to an 54538 * injector's bloom filter. 54539 * 54540 * @param di The node injector in which a directive will be added 54541 * @param token The type or the injection token to be made public 54542 */ 54543 54544 54545function diPublicInInjector(injectorIndex, tView, token) { 54546 bloomAdd(injectorIndex, tView, token); 54547} 54548/** 54549 * Inject static attribute value into directive constructor. 54550 * 54551 * This method is used with `factory` functions which are generated as part of 54552 * `defineDirective` or `defineComponent`. The method retrieves the static value 54553 * of an attribute. (Dynamic attributes are not supported since they are not resolved 54554 * at the time of injection and can change over time.) 54555 * 54556 * # Example 54557 * Given: 54558 * ``` 54559 * @Component(...) 54560 * class MyComponent { 54561 * constructor(@Attribute('title') title: string) { ... } 54562 * } 54563 * ``` 54564 * When instantiated with 54565 * ``` 54566 * <my-component title="Hello"></my-component> 54567 * ``` 54568 * 54569 * Then factory method generated is: 54570 * ``` 54571 * MyComponent.ɵcmp = defineComponent({ 54572 * factory: () => new MyComponent(injectAttribute('title')) 54573 * ... 54574 * }) 54575 * ``` 54576 * 54577 * @publicApi 54578 */ 54579 54580 54581function injectAttributeImpl(tNode, attrNameToInject) { 54582 ngDevMode && assertTNodeType(tNode, 12 54583 /* TNodeType.AnyContainer */ 54584 | 3 54585 /* TNodeType.AnyRNode */ 54586 ); 54587 ngDevMode && assertDefined(tNode, 'expecting tNode'); 54588 54589 if (attrNameToInject === 'class') { 54590 return tNode.classes; 54591 } 54592 54593 if (attrNameToInject === 'style') { 54594 return tNode.styles; 54595 } 54596 54597 const attrs = tNode.attrs; 54598 54599 if (attrs) { 54600 const attrsLength = attrs.length; 54601 let i = 0; 54602 54603 while (i < attrsLength) { 54604 const value = attrs[i]; // If we hit a `Bindings` or `Template` marker then we are done. 54605 54606 if (isNameOnlyAttributeMarker(value)) break; // Skip namespaced attributes 54607 54608 if (value === 0 54609 /* AttributeMarker.NamespaceURI */ 54610 ) { 54611 // we skip the next two values 54612 // as namespaced attributes looks like 54613 // [..., AttributeMarker.NamespaceURI, 'http://someuri.com/test', 'test:exist', 54614 // 'existValue', ...] 54615 i = i + 2; 54616 } else if (typeof value === 'number') { 54617 // Skip to the first value of the marked attribute. 54618 i++; 54619 54620 while (i < attrsLength && typeof attrs[i] === 'string') { 54621 i++; 54622 } 54623 } else if (value === attrNameToInject) { 54624 return attrs[i + 1]; 54625 } else { 54626 i = i + 2; 54627 } 54628 } 54629 } 54630 54631 return null; 54632} 54633 54634function notFoundValueOrThrow(notFoundValue, token, flags) { 54635 if (flags & InjectFlags.Optional || notFoundValue !== undefined) { 54636 return notFoundValue; 54637 } else { 54638 throwProviderNotFoundError(token, 'NodeInjector'); 54639 } 54640} 54641/** 54642 * Returns the value associated to the given token from the ModuleInjector or throws exception 54643 * 54644 * @param lView The `LView` that contains the `tNode` 54645 * @param token The token to look for 54646 * @param flags Injection flags 54647 * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional` 54648 * @returns the value from the injector or throws an exception 54649 */ 54650 54651 54652function lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue) { 54653 if (flags & InjectFlags.Optional && notFoundValue === undefined) { 54654 // This must be set or the NullInjector will throw for optional deps 54655 notFoundValue = null; 54656 } 54657 54658 if ((flags & (InjectFlags.Self | InjectFlags.Host)) === 0) { 54659 const moduleInjector = lView[INJECTOR$1]; // switch to `injectInjectorOnly` implementation for module injector, since module injector 54660 // should not have access to Component/Directive DI scope (that may happen through 54661 // `directiveInject` implementation) 54662 54663 const previousInjectImplementation = setInjectImplementation(undefined); 54664 54665 try { 54666 if (moduleInjector) { 54667 return moduleInjector.get(token, notFoundValue, flags & InjectFlags.Optional); 54668 } else { 54669 return injectRootLimpMode(token, notFoundValue, flags & InjectFlags.Optional); 54670 } 54671 } finally { 54672 setInjectImplementation(previousInjectImplementation); 54673 } 54674 } 54675 54676 return notFoundValueOrThrow(notFoundValue, token, flags); 54677} 54678/** 54679 * Returns the value associated to the given token from the NodeInjectors => ModuleInjector. 54680 * 54681 * Look for the injector providing the token by walking up the node injector tree and then 54682 * the module injector tree. 54683 * 54684 * This function patches `token` with `__NG_ELEMENT_ID__` which contains the id for the bloom 54685 * filter. `-1` is reserved for injecting `Injector` (implemented by `NodeInjector`) 54686 * 54687 * @param tNode The Node where the search for the injector should start 54688 * @param lView The `LView` that contains the `tNode` 54689 * @param token The token to look for 54690 * @param flags Injection flags 54691 * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional` 54692 * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided 54693 */ 54694 54695 54696function getOrCreateInjectable(tNode, lView, token, flags = InjectFlags.Default, notFoundValue) { 54697 if (tNode !== null) { 54698 // If the view or any of its ancestors have an embedded 54699 // view injector, we have to look it up there first. 54700 if (lView[FLAGS] & 1024 54701 /* LViewFlags.HasEmbeddedViewInjector */ 54702 ) { 54703 const embeddedInjectorValue = lookupTokenUsingEmbeddedInjector(tNode, lView, token, flags, NOT_FOUND); 54704 54705 if (embeddedInjectorValue !== NOT_FOUND) { 54706 return embeddedInjectorValue; 54707 } 54708 } // Otherwise try the node injector. 54709 54710 54711 const value = lookupTokenUsingNodeInjector(tNode, lView, token, flags, NOT_FOUND); 54712 54713 if (value !== NOT_FOUND) { 54714 return value; 54715 } 54716 } // Finally, fall back to the module injector. 54717 54718 54719 return lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue); 54720} 54721/** 54722 * Returns the value associated to the given token from the node injector. 54723 * 54724 * @param tNode The Node where the search for the injector should start 54725 * @param lView The `LView` that contains the `tNode` 54726 * @param token The token to look for 54727 * @param flags Injection flags 54728 * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional` 54729 * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided 54730 */ 54731 54732 54733function lookupTokenUsingNodeInjector(tNode, lView, token, flags, notFoundValue) { 54734 const bloomHash = bloomHashBitOrFactory(token); // If the ID stored here is a function, this is a special object like ElementRef or TemplateRef 54735 // so just call the factory function to create it. 54736 54737 if (typeof bloomHash === 'function') { 54738 if (!enterDI(lView, tNode, flags)) { 54739 // Failed to enter DI, try module injector instead. If a token is injected with the @Host 54740 // flag, the module injector is not searched for that token in Ivy. 54741 return flags & InjectFlags.Host ? notFoundValueOrThrow(notFoundValue, token, flags) : lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue); 54742 } 54743 54744 try { 54745 const value = bloomHash(flags); 54746 54747 if (value == null && !(flags & InjectFlags.Optional)) { 54748 throwProviderNotFoundError(token); 54749 } else { 54750 return value; 54751 } 54752 } finally { 54753 leaveDI(); 54754 } 54755 } else if (typeof bloomHash === 'number') { 54756 // A reference to the previous injector TView that was found while climbing the element 54757 // injector tree. This is used to know if viewProviders can be accessed on the current 54758 // injector. 54759 let previousTView = null; 54760 let injectorIndex = getInjectorIndex(tNode, lView); 54761 let parentLocation = NO_PARENT_INJECTOR; 54762 let hostTElementNode = flags & InjectFlags.Host ? lView[DECLARATION_COMPONENT_VIEW][T_HOST] : null; // If we should skip this injector, or if there is no injector on this node, start by 54763 // searching the parent injector. 54764 54765 if (injectorIndex === -1 || flags & InjectFlags.SkipSelf) { 54766 parentLocation = injectorIndex === -1 ? getParentInjectorLocation(tNode, lView) : lView[injectorIndex + 8 54767 /* NodeInjectorOffset.PARENT */ 54768 ]; 54769 54770 if (parentLocation === NO_PARENT_INJECTOR || !shouldSearchParent(flags, false)) { 54771 injectorIndex = -1; 54772 } else { 54773 previousTView = lView[TVIEW]; 54774 injectorIndex = getParentInjectorIndex(parentLocation); 54775 lView = getParentInjectorView(parentLocation, lView); 54776 } 54777 } // Traverse up the injector tree until we find a potential match or until we know there 54778 // *isn't* a match. 54779 54780 54781 while (injectorIndex !== -1) { 54782 ngDevMode && assertNodeInjector(lView, injectorIndex); // Check the current injector. If it matches, see if it contains token. 54783 54784 const tView = lView[TVIEW]; 54785 ngDevMode && assertTNodeForLView(tView.data[injectorIndex + 8 54786 /* NodeInjectorOffset.TNODE */ 54787 ], lView); 54788 54789 if (bloomHasToken(bloomHash, injectorIndex, tView.data)) { 54790 // At this point, we have an injector which *may* contain the token, so we step through 54791 // the providers and directives associated with the injector's corresponding node to get 54792 // the instance. 54793 const instance = searchTokensOnInjector(injectorIndex, lView, token, previousTView, flags, hostTElementNode); 54794 54795 if (instance !== NOT_FOUND) { 54796 return instance; 54797 } 54798 } 54799 54800 parentLocation = lView[injectorIndex + 8 54801 /* NodeInjectorOffset.PARENT */ 54802 ]; 54803 54804 if (parentLocation !== NO_PARENT_INJECTOR && shouldSearchParent(flags, lView[TVIEW].data[injectorIndex + 8 54805 /* NodeInjectorOffset.TNODE */ 54806 ] === hostTElementNode) && bloomHasToken(bloomHash, injectorIndex, lView)) { 54807 // The def wasn't found anywhere on this node, so it was a false positive. 54808 // Traverse up the tree and continue searching. 54809 previousTView = tView; 54810 injectorIndex = getParentInjectorIndex(parentLocation); 54811 lView = getParentInjectorView(parentLocation, lView); 54812 } else { 54813 // If we should not search parent OR If the ancestor bloom filter value does not have the 54814 // bit corresponding to the directive we can give up on traversing up to find the specific 54815 // injector. 54816 injectorIndex = -1; 54817 } 54818 } 54819 } 54820 54821 return notFoundValue; 54822} 54823 54824function searchTokensOnInjector(injectorIndex, lView, token, previousTView, flags, hostTElementNode) { 54825 const currentTView = lView[TVIEW]; 54826 const tNode = currentTView.data[injectorIndex + 8 54827 /* NodeInjectorOffset.TNODE */ 54828 ]; // First, we need to determine if view providers can be accessed by the starting element. 54829 // There are two possibilities 54830 54831 const canAccessViewProviders = previousTView == null ? // 1) This is the first invocation `previousTView == null` which means that we are at the 54832 // `TNode` of where injector is starting to look. In such a case the only time we are allowed 54833 // to look into the ViewProviders is if: 54834 // - we are on a component 54835 // - AND the injector set `includeViewProviders` to true (implying that the token can see 54836 // ViewProviders because it is the Component or a Service which itself was declared in 54837 // ViewProviders) 54838 isComponentHost(tNode) && includeViewProviders : // 2) `previousTView != null` which means that we are now walking across the parent nodes. 54839 // In such a case we are only allowed to look into the ViewProviders if: 54840 // - We just crossed from child View to Parent View `previousTView != currentTView` 54841 // - AND the parent TNode is an Element. 54842 // This means that we just came from the Component's View and therefore are allowed to see 54843 // into the ViewProviders. 54844 previousTView != currentTView && (tNode.type & 3 54845 /* TNodeType.AnyRNode */ 54846 ) !== 0; // This special case happens when there is a @host on the inject and when we are searching 54847 // on the host element node. 54848 54849 const isHostSpecialCase = flags & InjectFlags.Host && hostTElementNode === tNode; 54850 const injectableIdx = locateDirectiveOrProvider(tNode, currentTView, token, canAccessViewProviders, isHostSpecialCase); 54851 54852 if (injectableIdx !== null) { 54853 return getNodeInjectable(lView, currentTView, injectableIdx, tNode); 54854 } else { 54855 return NOT_FOUND; 54856 } 54857} 54858/** 54859 * Searches for the given token among the node's directives and providers. 54860 * 54861 * @param tNode TNode on which directives are present. 54862 * @param tView The tView we are currently processing 54863 * @param token Provider token or type of a directive to look for. 54864 * @param canAccessViewProviders Whether view providers should be considered. 54865 * @param isHostSpecialCase Whether the host special case applies. 54866 * @returns Index of a found directive or provider, or null when none found. 54867 */ 54868 54869 54870function locateDirectiveOrProvider(tNode, tView, token, canAccessViewProviders, isHostSpecialCase) { 54871 const nodeProviderIndexes = tNode.providerIndexes; 54872 const tInjectables = tView.data; 54873 const injectablesStart = nodeProviderIndexes & 1048575 54874 /* TNodeProviderIndexes.ProvidersStartIndexMask */ 54875 ; 54876 const directivesStart = tNode.directiveStart; 54877 const directiveEnd = tNode.directiveEnd; 54878 const cptViewProvidersCount = nodeProviderIndexes >> 20 54879 /* TNodeProviderIndexes.CptViewProvidersCountShift */ 54880 ; 54881 const startingIndex = canAccessViewProviders ? injectablesStart : injectablesStart + cptViewProvidersCount; // When the host special case applies, only the viewProviders and the component are visible 54882 54883 const endIndex = isHostSpecialCase ? injectablesStart + cptViewProvidersCount : directiveEnd; 54884 54885 for (let i = startingIndex; i < endIndex; i++) { 54886 const providerTokenOrDef = tInjectables[i]; 54887 54888 if (i < directivesStart && token === providerTokenOrDef || i >= directivesStart && providerTokenOrDef.type === token) { 54889 return i; 54890 } 54891 } 54892 54893 if (isHostSpecialCase) { 54894 const dirDef = tInjectables[directivesStart]; 54895 54896 if (dirDef && isComponentDef(dirDef) && dirDef.type === token) { 54897 return directivesStart; 54898 } 54899 } 54900 54901 return null; 54902} 54903/** 54904 * Retrieve or instantiate the injectable from the `LView` at particular `index`. 54905 * 54906 * This function checks to see if the value has already been instantiated and if so returns the 54907 * cached `injectable`. Otherwise if it detects that the value is still a factory it 54908 * instantiates the `injectable` and caches the value. 54909 */ 54910 54911 54912function getNodeInjectable(lView, tView, index, tNode) { 54913 let value = lView[index]; 54914 const tData = tView.data; 54915 54916 if (isFactory(value)) { 54917 const factory = value; 54918 54919 if (factory.resolving) { 54920 throwCyclicDependencyError(stringifyForError(tData[index])); 54921 } 54922 54923 const previousIncludeViewProviders = setIncludeViewProviders(factory.canSeeViewProviders); 54924 factory.resolving = true; 54925 const previousInjectImplementation = factory.injectImpl ? setInjectImplementation(factory.injectImpl) : null; 54926 const success = enterDI(lView, tNode, InjectFlags.Default); 54927 ngDevMode && assertEqual(success, true, 'Because flags do not contain \`SkipSelf\' we expect this to always succeed.'); 54928 54929 try { 54930 value = lView[index] = factory.factory(undefined, tData, lView, tNode); // This code path is hit for both directives and providers. 54931 // For perf reasons, we want to avoid searching for hooks on providers. 54932 // It does no harm to try (the hooks just won't exist), but the extra 54933 // checks are unnecessary and this is a hot path. So we check to see 54934 // if the index of the dependency is in the directive range for this 54935 // tNode. If it's not, we know it's a provider and skip hook registration. 54936 54937 if (tView.firstCreatePass && index >= tNode.directiveStart) { 54938 ngDevMode && assertDirectiveDef(tData[index]); 54939 registerPreOrderHooks(index, tData[index], tView); 54940 } 54941 } finally { 54942 previousInjectImplementation !== null && setInjectImplementation(previousInjectImplementation); 54943 setIncludeViewProviders(previousIncludeViewProviders); 54944 factory.resolving = false; 54945 leaveDI(); 54946 } 54947 } 54948 54949 return value; 54950} 54951/** 54952 * Returns the bit in an injector's bloom filter that should be used to determine whether or not 54953 * the directive might be provided by the injector. 54954 * 54955 * When a directive is public, it is added to the bloom filter and given a unique ID that can be 54956 * retrieved on the Type. When the directive isn't public or the token is not a directive `null` 54957 * is returned as the node injector can not possibly provide that token. 54958 * 54959 * @param token the injection token 54960 * @returns the matching bit to check in the bloom filter or `null` if the token is not known. 54961 * When the returned value is negative then it represents special values such as `Injector`. 54962 */ 54963 54964 54965function bloomHashBitOrFactory(token) { 54966 ngDevMode && assertDefined(token, 'token must be defined'); 54967 54968 if (typeof token === 'string') { 54969 return token.charCodeAt(0) || 0; 54970 } 54971 54972 const tokenId = // First check with `hasOwnProperty` so we don't get an inherited ID. 54973 token.hasOwnProperty(NG_ELEMENT_ID) ? token[NG_ELEMENT_ID] : undefined; // Negative token IDs are used for special objects such as `Injector` 54974 54975 if (typeof tokenId === 'number') { 54976 if (tokenId >= 0) { 54977 return tokenId & BLOOM_MASK; 54978 } else { 54979 ngDevMode && assertEqual(tokenId, -1 54980 /* InjectorMarkers.Injector */ 54981 , 'Expecting to get Special Injector Id'); 54982 return createNodeInjector; 54983 } 54984 } else { 54985 return tokenId; 54986 } 54987} 54988 54989function bloomHasToken(bloomHash, injectorIndex, injectorView) { 54990 // Create a mask that targets the specific bit associated with the directive we're looking for. 54991 // JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding 54992 // to bit positions 0 - 31 in a 32 bit integer. 54993 const mask = 1 << bloomHash; // Each bloom bucket in `injectorView` represents `BLOOM_BUCKET_BITS` number of bits of 54994 // `bloomHash`. Any bits in `bloomHash` beyond `BLOOM_BUCKET_BITS` indicate the bucket offset 54995 // that should be used. 54996 54997 const value = injectorView[injectorIndex + (bloomHash >> BLOOM_BUCKET_BITS)]; // If the bloom filter value has the bit corresponding to the directive's bloomBit flipped on, 54998 // this injector is a potential match. 54999 55000 return !!(value & mask); 55001} 55002/** Returns true if flags prevent parent injector from being searched for tokens */ 55003 55004 55005function shouldSearchParent(flags, isFirstHostTNode) { 55006 return !(flags & InjectFlags.Self) && !(flags & InjectFlags.Host && isFirstHostTNode); 55007} 55008 55009class NodeInjector { 55010 constructor(_tNode, _lView) { 55011 this._tNode = _tNode; 55012 this._lView = _lView; 55013 } 55014 55015 get(token, notFoundValue, flags) { 55016 return getOrCreateInjectable(this._tNode, this._lView, token, flags, notFoundValue); 55017 } 55018 55019} 55020/** Creates a `NodeInjector` for the current node. */ 55021 55022 55023function createNodeInjector() { 55024 return new NodeInjector(getCurrentTNode(), getLView()); 55025} 55026/** 55027 * @codeGenApi 55028 */ 55029 55030 55031function ɵɵgetInheritedFactory(type) { 55032 return noSideEffects(() => { 55033 const ownConstructor = type.prototype.constructor; 55034 const ownFactory = ownConstructor[NG_FACTORY_DEF] || getFactoryOf(ownConstructor); 55035 const objectPrototype = Object.prototype; 55036 let parent = Object.getPrototypeOf(type.prototype).constructor; // Go up the prototype until we hit `Object`. 55037 55038 while (parent && parent !== objectPrototype) { 55039 const factory = parent[NG_FACTORY_DEF] || getFactoryOf(parent); // If we hit something that has a factory and the factory isn't the same as the type, 55040 // we've found the inherited factory. Note the check that the factory isn't the type's 55041 // own factory is redundant in most cases, but if the user has custom decorators on the 55042 // class, this lookup will start one level down in the prototype chain, causing us to 55043 // find the own factory first and potentially triggering an infinite loop downstream. 55044 55045 if (factory && factory !== ownFactory) { 55046 return factory; 55047 } 55048 55049 parent = Object.getPrototypeOf(parent); 55050 } // There is no factory defined. Either this was improper usage of inheritance 55051 // (no Angular decorator on the superclass) or there is no constructor at all 55052 // in the inheritance chain. Since the two cases cannot be distinguished, the 55053 // latter has to be assumed. 55054 55055 55056 return t => new t(); 55057 }); 55058} 55059 55060function getFactoryOf(type) { 55061 if (isForwardRef(type)) { 55062 return () => { 55063 const factory = getFactoryOf(resolveForwardRef(type)); 55064 return factory && factory(); 55065 }; 55066 } 55067 55068 return getFactoryDef(type); 55069} 55070/** 55071 * Returns a value from the closest embedded or node injector. 55072 * 55073 * @param tNode The Node where the search for the injector should start 55074 * @param lView The `LView` that contains the `tNode` 55075 * @param token The token to look for 55076 * @param flags Injection flags 55077 * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional` 55078 * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided 55079 */ 55080 55081 55082function lookupTokenUsingEmbeddedInjector(tNode, lView, token, flags, notFoundValue) { 55083 let currentTNode = tNode; 55084 let currentLView = lView; // When an LView with an embedded view injector is inserted, it'll likely be interlaced with 55085 // nodes who may have injectors (e.g. node injector -> embedded view injector -> node injector). 55086 // Since the bloom filters for the node injectors have already been constructed and we don't 55087 // have a way of extracting the records from an injector, the only way to maintain the correct 55088 // hierarchy when resolving the value is to walk it node-by-node while attempting to resolve 55089 // the token at each level. 55090 55091 while (currentTNode !== null && currentLView !== null && currentLView[FLAGS] & 1024 55092 /* LViewFlags.HasEmbeddedViewInjector */ 55093 && !(currentLView[FLAGS] & 256 55094 /* LViewFlags.IsRoot */ 55095 )) { 55096 ngDevMode && assertTNodeForLView(currentTNode, currentLView); // Note that this lookup on the node injector is using the `Self` flag, because 55097 // we don't want the node injector to look at any parent injectors since we 55098 // may hit the embedded view injector first. 55099 55100 const nodeInjectorValue = lookupTokenUsingNodeInjector(currentTNode, currentLView, token, flags | InjectFlags.Self, NOT_FOUND); 55101 55102 if (nodeInjectorValue !== NOT_FOUND) { 55103 return nodeInjectorValue; 55104 } // Has an explicit type due to a TS bug: https://github.com/microsoft/TypeScript/issues/33191 55105 55106 55107 let parentTNode = currentTNode.parent; // `TNode.parent` includes the parent within the current view only. If it doesn't exist, 55108 // it means that we've hit the view boundary and we need to go up to the next view. 55109 55110 if (!parentTNode) { 55111 // Before we go to the next LView, check if the token exists on the current embedded injector. 55112 const embeddedViewInjector = currentLView[EMBEDDED_VIEW_INJECTOR]; 55113 55114 if (embeddedViewInjector) { 55115 const embeddedViewInjectorValue = embeddedViewInjector.get(token, NOT_FOUND, flags); 55116 55117 if (embeddedViewInjectorValue !== NOT_FOUND) { 55118 return embeddedViewInjectorValue; 55119 } 55120 } // Otherwise keep going up the tree. 55121 55122 55123 parentTNode = getTNodeFromLView(currentLView); 55124 currentLView = currentLView[DECLARATION_VIEW]; 55125 } 55126 55127 currentTNode = parentTNode; 55128 } 55129 55130 return notFoundValue; 55131} 55132/** Gets the TNode associated with an LView inside of the declaration view. */ 55133 55134 55135function getTNodeFromLView(lView) { 55136 const tView = lView[TVIEW]; 55137 const tViewType = tView.type; // The parent pointer differs based on `TView.type`. 55138 55139 if (tViewType === 2 55140 /* TViewType.Embedded */ 55141 ) { 55142 ngDevMode && assertDefined(tView.declTNode, 'Embedded TNodes should have declaration parents.'); 55143 return tView.declTNode; 55144 } else if (tViewType === 1 55145 /* TViewType.Component */ 55146 ) { 55147 // Components don't have `TView.declTNode` because each instance of component could be 55148 // inserted in different location, hence `TView.declTNode` is meaningless. 55149 return lView[T_HOST]; 55150 } 55151 55152 return null; 55153} 55154/** 55155 * @license 55156 * Copyright Google LLC All Rights Reserved. 55157 * 55158 * Use of this source code is governed by an MIT-style license that can be 55159 * found in the LICENSE file at https://angular.io/license 55160 */ 55161 55162/** 55163 * Facade for the attribute injection from DI. 55164 * 55165 * @codeGenApi 55166 */ 55167 55168 55169function ɵɵinjectAttribute(attrNameToInject) { 55170 return injectAttributeImpl(getCurrentTNode(), attrNameToInject); 55171} 55172/** 55173 * @license 55174 * Copyright Google LLC All Rights Reserved. 55175 * 55176 * Use of this source code is governed by an MIT-style license that can be 55177 * found in the LICENSE file at https://angular.io/license 55178 */ 55179 55180 55181const ANNOTATIONS = '__annotations__'; 55182const PARAMETERS = '__parameters__'; 55183const PROP_METADATA = '__prop__metadata__'; 55184/** 55185 * @suppress {globalThis} 55186 */ 55187 55188function makeDecorator(name, props, parentClass, additionalProcessing, typeFn) { 55189 return noSideEffects(() => { 55190 const metaCtor = makeMetadataCtor(props); 55191 55192 function DecoratorFactory(...args) { 55193 if (this instanceof DecoratorFactory) { 55194 metaCtor.call(this, ...args); 55195 return this; 55196 } 55197 55198 const annotationInstance = new DecoratorFactory(...args); 55199 return function TypeDecorator(cls) { 55200 if (typeFn) typeFn(cls, ...args); // Use of Object.defineProperty is important since it creates non-enumerable property which 55201 // prevents the property is copied during subclassing. 55202 55203 const annotations = cls.hasOwnProperty(ANNOTATIONS) ? cls[ANNOTATIONS] : Object.defineProperty(cls, ANNOTATIONS, { 55204 value: [] 55205 })[ANNOTATIONS]; 55206 annotations.push(annotationInstance); 55207 if (additionalProcessing) additionalProcessing(cls); 55208 return cls; 55209 }; 55210 } 55211 55212 if (parentClass) { 55213 DecoratorFactory.prototype = Object.create(parentClass.prototype); 55214 } 55215 55216 DecoratorFactory.prototype.ngMetadataName = name; 55217 DecoratorFactory.annotationCls = DecoratorFactory; 55218 return DecoratorFactory; 55219 }); 55220} 55221 55222function makeMetadataCtor(props) { 55223 return function ctor(...args) { 55224 if (props) { 55225 const values = props(...args); 55226 55227 for (const propName in values) { 55228 this[propName] = values[propName]; 55229 } 55230 } 55231 }; 55232} 55233 55234function makeParamDecorator(name, props, parentClass) { 55235 return noSideEffects(() => { 55236 const metaCtor = makeMetadataCtor(props); 55237 55238 function ParamDecoratorFactory(...args) { 55239 if (this instanceof ParamDecoratorFactory) { 55240 metaCtor.apply(this, args); 55241 return this; 55242 } 55243 55244 const annotationInstance = new ParamDecoratorFactory(...args); 55245 ParamDecorator.annotation = annotationInstance; 55246 return ParamDecorator; 55247 55248 function ParamDecorator(cls, unusedKey, index) { 55249 // Use of Object.defineProperty is important since it creates non-enumerable property which 55250 // prevents the property is copied during subclassing. 55251 const parameters = cls.hasOwnProperty(PARAMETERS) ? cls[PARAMETERS] : Object.defineProperty(cls, PARAMETERS, { 55252 value: [] 55253 })[PARAMETERS]; // there might be gaps if some in between parameters do not have annotations. 55254 // we pad with nulls. 55255 55256 while (parameters.length <= index) { 55257 parameters.push(null); 55258 } 55259 55260 (parameters[index] = parameters[index] || []).push(annotationInstance); 55261 return cls; 55262 } 55263 } 55264 55265 if (parentClass) { 55266 ParamDecoratorFactory.prototype = Object.create(parentClass.prototype); 55267 } 55268 55269 ParamDecoratorFactory.prototype.ngMetadataName = name; 55270 ParamDecoratorFactory.annotationCls = ParamDecoratorFactory; 55271 return ParamDecoratorFactory; 55272 }); 55273} 55274 55275function makePropDecorator(name, props, parentClass, additionalProcessing) { 55276 return noSideEffects(() => { 55277 const metaCtor = makeMetadataCtor(props); 55278 55279 function PropDecoratorFactory(...args) { 55280 if (this instanceof PropDecoratorFactory) { 55281 metaCtor.apply(this, args); 55282 return this; 55283 } 55284 55285 const decoratorInstance = new PropDecoratorFactory(...args); 55286 55287 function PropDecorator(target, name) { 55288 const constructor = target.constructor; // Use of Object.defineProperty is important because it creates a non-enumerable property 55289 // which prevents the property from being copied during subclassing. 55290 55291 const meta = constructor.hasOwnProperty(PROP_METADATA) ? constructor[PROP_METADATA] : Object.defineProperty(constructor, PROP_METADATA, { 55292 value: {} 55293 })[PROP_METADATA]; 55294 meta[name] = meta.hasOwnProperty(name) && meta[name] || []; 55295 meta[name].unshift(decoratorInstance); 55296 if (additionalProcessing) additionalProcessing(target, name, ...args); 55297 } 55298 55299 return PropDecorator; 55300 } 55301 55302 if (parentClass) { 55303 PropDecoratorFactory.prototype = Object.create(parentClass.prototype); 55304 } 55305 55306 PropDecoratorFactory.prototype.ngMetadataName = name; 55307 PropDecoratorFactory.annotationCls = PropDecoratorFactory; 55308 return PropDecoratorFactory; 55309 }); 55310} 55311/** 55312 * @license 55313 * Copyright Google LLC All Rights Reserved. 55314 * 55315 * Use of this source code is governed by an MIT-style license that can be 55316 * found in the LICENSE file at https://angular.io/license 55317 */ 55318 55319/** 55320 * Attribute decorator and metadata. 55321 * 55322 * @Annotation 55323 * @publicApi 55324 */ 55325 55326 55327const Attribute = makeParamDecorator('Attribute', attributeName => ({ 55328 attributeName, 55329 __NG_ELEMENT_ID__: () => ɵɵinjectAttribute(attributeName) 55330})); 55331/** 55332 * @license 55333 * Copyright Google LLC All Rights Reserved. 55334 * 55335 * Use of this source code is governed by an MIT-style license that can be 55336 * found in the LICENSE file at https://angular.io/license 55337 */ 55338 55339/** 55340 * Creates a token that can be used in a DI Provider. 55341 * 55342 * Use an `InjectionToken` whenever the type you are injecting is not reified (does not have a 55343 * runtime representation) such as when injecting an interface, callable type, array or 55344 * parameterized type. 55345 * 55346 * `InjectionToken` is parameterized on `T` which is the type of object which will be returned by 55347 * the `Injector`. This provides an additional level of type safety. 55348 * 55349 * ``` 55350 * interface MyInterface {...} 55351 * const myInterface = injector.get(new InjectionToken<MyInterface>('SomeToken')); 55352 * // myInterface is inferred to be MyInterface. 55353 * ``` 55354 * 55355 * When creating an `InjectionToken`, you can optionally specify a factory function which returns 55356 * (possibly by creating) a default value of the parameterized type `T`. This sets up the 55357 * `InjectionToken` using this factory as a provider as if it was defined explicitly in the 55358 * application's root injector. If the factory function, which takes zero arguments, needs to inject 55359 * dependencies, it can do so using the `inject` function. 55360 * As you can see in the Tree-shakable InjectionToken example below.
55361 * 55362 * Additionally, if a `factory` is specified you can also specify the `providedIn` option, which 55363 * overrides the above behavior and marks the token as belonging to a particular `@NgModule`. As 55364 * mentioned above, `'root'` is the default value for `providedIn`. 55365 * 55366 * @usageNotes 55367 * ### Basic Examples 55368 * 55369 * ### Plain InjectionToken 55370 * 55371 * {@example core/di/ts/injector_spec.ts region='InjectionToken'} 55372 * 55373 * ### Tree-shakable InjectionToken 55374 * 55375 * {@example core/di/ts/injector_spec.ts region='ShakableInjectionToken'} 55376 * 55377 * 55378 * @publicApi 55379 */ 55380 55381class InjectionToken { 55382 /** 55383 * @param _desc Description for the token, 55384 * used only for debugging purposes, 55385 * it should but does not need to be unique 55386 * @param options Options for the token's usage, as described above 55387 */ 55388 constructor(_desc, options) { 55389 this._desc = _desc; 55390 /** @internal */ 55391 55392 this.ngMetadataName = 'InjectionToken'; 55393 this.ɵprov = undefined; 55394 55395 if (typeof options == 'number') { 55396 (typeof ngDevMode === 'undefined' || ngDevMode) && assertLessThan(options, 0, 'Only negative numbers are supported here'); // This is a special hack to assign __NG_ELEMENT_ID__ to this instance. 55397 // See `InjectorMarkers` 55398 55399 this.__NG_ELEMENT_ID__ = options; 55400 } else if (options !== undefined) { 55401 this.ɵprov = ɵɵdefineInjectable({ 55402 token: this, 55403 providedIn: options.providedIn || 'root', 55404 factory: options.factory 55405 }); 55406 } 55407 } 55408 /** 55409 * @internal 55410 */ 55411 55412 55413 get multi() { 55414 return this; 55415 } 55416 55417 toString() { 55418 return `InjectionToken ${this._desc}`; 55419 } 55420 55421} 55422/** 55423 * @license 55424 * Copyright Google LLC All Rights Reserved. 55425 * 55426 * Use of this source code is governed by an MIT-style license that can be 55427 * found in the LICENSE file at https://angular.io/license 55428 */ 55429 55430/** 55431 * A DI token that you can use to create a virtual [provider](guide/glossary#provider) 55432 * that will populate the `entryComponents` field of components and NgModules 55433 * based on its `useValue` property value. 55434 * All components that are referenced in the `useValue` value (either directly 55435 * or in a nested array or map) are added to the `entryComponents` property. 55436 * 55437 * @usageNotes 55438 * 55439 * The following example shows how the router can populate the `entryComponents` 55440 * field of an NgModule based on a router configuration that refers 55441 * to components. 55442 * 55443 * ```typescript 55444 * // helper function inside the router 55445 * function provideRoutes(routes) { 55446 * return [ 55447 * {provide: ROUTES, useValue: routes}, 55448 * {provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: routes, multi: true} 55449 * ]; 55450 * } 55451 * 55452 * // user code 55453 * let routes = [ 55454 * {path: '/root', component: RootComp}, 55455 * {path: '/teams', component: TeamsComp} 55456 * ]; 55457 * 55458 * @NgModule({ 55459 * providers: [provideRoutes(routes)] 55460 * }) 55461 * class ModuleWithRoutes {} 55462 * ``` 55463 * 55464 * @publicApi 55465 * @deprecated Since 9.0.0. With Ivy, this property is no longer necessary. 55466 */ 55467 55468 55469const ANALYZE_FOR_ENTRY_COMPONENTS = new InjectionToken('AnalyzeForEntryComponents'); // Stores the default value of `emitDistinctChangesOnly` when the `emitDistinctChangesOnly` is not 55470// explicitly set. 55471 55472const emitDistinctChangesOnlyDefaultValue = true; 55473/** 55474 * Base class for query metadata. 55475 * 55476 * @see `ContentChildren`. 55477 * @see `ContentChild`. 55478 * @see `ViewChildren`. 55479 * @see `ViewChild`. 55480 * 55481 * @publicApi 55482 */ 55483 55484class Query {} 55485/** 55486 * ContentChildren decorator and metadata. 55487 * 55488 * 55489 * @Annotation 55490 * @publicApi 55491 */ 55492 55493 55494const ContentChildren = makePropDecorator('ContentChildren', (selector, data = {}) => ({ 55495 selector, 55496 first: false, 55497 isViewQuery: false, 55498 descendants: false, 55499 emitDistinctChangesOnly: emitDistinctChangesOnlyDefaultValue, 55500 ...data 55501}), Query); 55502/** 55503 * ContentChild decorator and metadata. 55504 * 55505 * 55506 * @Annotation 55507 * 55508 * @publicApi 55509 */ 55510 55511const ContentChild = makePropDecorator('ContentChild', (selector, data = {}) => ({ 55512 selector, 55513 first: true, 55514 isViewQuery: false, 55515 descendants: true, 55516 ...data 55517}), Query); 55518/** 55519 * ViewChildren decorator and metadata. 55520 * 55521 * @Annotation 55522 * @publicApi 55523 */ 55524 55525const ViewChildren = makePropDecorator('ViewChildren', (selector, data = {}) => ({ 55526 selector, 55527 first: false, 55528 isViewQuery: true, 55529 descendants: true, 55530 emitDistinctChangesOnly: emitDistinctChangesOnlyDefaultValue, 55531 ...data 55532}), Query); 55533/** 55534 * ViewChild decorator and metadata. 55535 * 55536 * @Annotation 55537 * @publicApi 55538 */ 55539 55540const ViewChild = makePropDecorator('ViewChild', (selector, data) => ({ 55541 selector, 55542 first: true, 55543 isViewQuery: true, 55544 descendants: true, 55545 ...data 55546}), Query); 55547/** 55548 * @license 55549 * Copyright Google LLC All Rights Reserved. 55550 * 55551 * Use of this source code is governed by an MIT-style license that can be 55552 * found in the LICENSE file at https://angular.io/license 55553 */ 55554 55555var FactoryTarget; 55556 55557(function (FactoryTarget) { 55558 FactoryTarget[FactoryTarget["Directive"] = 0] = "Directive"; 55559 FactoryTarget[FactoryTarget["Component"] = 1] = "Component"; 55560 FactoryTarget[FactoryTarget["Injectable"] = 2] = "Injectable"; 55561 FactoryTarget[FactoryTarget["Pipe"] = 3] = "Pipe"; 55562 FactoryTarget[FactoryTarget["NgModule"] = 4] = "NgModule"; 55563})(FactoryTarget || (FactoryTarget = {})); 55564 55565var R3TemplateDependencyKind; 55566 55567(function (R3TemplateDependencyKind) { 55568 R3TemplateDependencyKind[R3TemplateDependencyKind["Directive"] = 0] = "Directive"; 55569 R3TemplateDependencyKind[R3TemplateDependencyKind["Pipe"] = 1] = "Pipe"; 55570 R3TemplateDependencyKind[R3TemplateDependencyKind["NgModule"] = 2] = "NgModule"; 55571})(R3TemplateDependencyKind || (R3TemplateDependencyKind = {})); 55572 55573var ViewEncapsulation; 55574 55575(function (ViewEncapsulation) { 55576 ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated"; // Historically the 1 value was for `Native` encapsulation which has been removed as of v11. 55577 55578 ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None"; 55579 ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom"; 55580})(ViewEncapsulation || (ViewEncapsulation = {})); 55581/** 55582 * @license 55583 * Copyright Google LLC All Rights Reserved. 55584 * 55585 * Use of this source code is governed by an MIT-style license that can be 55586 * found in the LICENSE file at https://angular.io/license 55587 */ 55588 55589 55590function getCompilerFacade(request) { 55591 const globalNg = _global['ng']; 55592 55593 if (globalNg && globalNg.ɵcompilerFacade) { 55594 return globalNg.ɵcompilerFacade; 55595 } 55596 55597 if (typeof ngDevMode === 'undefined' || ngDevMode) { 55598 // Log the type as an error so that a developer can easily navigate to the type from the 55599 // console. 55600 console.error(`JIT compilation failed for ${request.kind}`, request.type); 55601 let message = `The ${request.kind} '${request.type.name}' needs to be compiled using the JIT compiler, but '@angular/compiler' is not available.\n\n`; 55602 55603 if (request.usage === 1 55604 /* JitCompilerUsage.PartialDeclaration */ 55605 ) { 55606 message += `The ${request.kind} is part of a library that has been partially compiled.\n`; 55607 message += `However, the Angular Linker has not processed the library such that JIT compilation is used as fallback.\n`; 55608 message += '\n'; 55609 message += `Ideally, the library is processed using the Angular Linker to become fully AOT compiled.\n`; 55610 } else { 55611 message += `JIT compilation is discouraged for production use-cases! Consider using AOT mode instead.\n`; 55612 } 55613 55614 message += `Alternatively, the JIT compiler should be loaded by bootstrapping using '@angular/platform-browser-dynamic' or '@angular/platform-server',\n`; 55615 message += `or manually provide the compiler with 'import "@angular/compiler";' before bootstrapping.`; 55616 throw new Error(message); 55617 } else { 55618 throw new Error('JIT compiler unavailable'); 55619 } 55620} 55621/** 55622 * @license 55623 * Copyright Google LLC All Rights Reserved. 55624 * 55625 * Use of this source code is governed by an MIT-style license that can be 55626 * found in the LICENSE file at https://angular.io/license 55627 */ 55628 55629/** 55630 * @description 55631 * 55632 * Represents a type that a Component or other object is instances of. 55633 * 55634 * An example of a `Type` is `MyCustomComponent` class, which in JavaScript is represented by 55635 * the `MyCustomComponent` constructor function. 55636 * 55637 * @publicApi 55638 */ 55639 55640 55641const Type = Function; 55642 55643function isType(v) { 55644 return typeof v === 'function'; 55645} 55646/** 55647 * @license 55648 * Copyright Google LLC All Rights Reserved. 55649 * 55650 * Use of this source code is governed by an MIT-style license that can be 55651 * found in the LICENSE file at https://angular.io/license 55652 */ 55653 55654/** 55655 * Equivalent to ES6 spread, add each item to an array.
vendor: 18,225 bytes, lines 55656-56280
55656 * 55657 * @param items The items to add 55658 * @param arr The array to which you want to add the items 55659 */ 55660 55661 55662function addAllToArray(items, arr) { 55663 for (let i = 0; i < items.length; i++) { 55664 arr.push(items[i]); 55665 } 55666} 55667/** 55668 * Determines if the contents of two arrays is identical 55669 * 55670 * @param a first array 55671 * @param b second array 55672 * @param identityAccessor Optional function for extracting stable object identity from a value in 55673 * the array. 55674 */ 55675 55676 55677function arrayEquals(a, b, identityAccessor) { 55678 if (a.length !== b.length) return false; 55679 55680 for (let i = 0; i < a.length; i++) { 55681 let valueA = a[i]; 55682 let valueB = b[i]; 55683 55684 if (identityAccessor) { 55685 valueA = identityAccessor(valueA); 55686 valueB = identityAccessor(valueB); 55687 } 55688 55689 if (valueB !== valueA) { 55690 return false; 55691 } 55692 } 55693 55694 return true; 55695} 55696/** 55697 * Flattens an array. 55698 */ 55699 55700 55701function flatten(list, dst) { 55702 if (dst === undefined) dst = list; 55703 55704 for (let i = 0; i < list.length; i++) { 55705 let item = list[i]; 55706 55707 if (Array.isArray(item)) { 55708 // we need to inline it. 55709 if (dst === list) { 55710 // Our assumption that the list was already flat was wrong and 55711 // we need to clone flat since we need to write to it. 55712 dst = list.slice(0, i); 55713 } 55714 55715 flatten(item, dst); 55716 } else if (dst !== list) { 55717 dst.push(item); 55718 } 55719 } 55720 55721 return dst; 55722} 55723 55724function deepForEach(input, fn) { 55725 input.forEach(value => Array.isArray(value) ? deepForEach(value, fn) : fn(value)); 55726} 55727 55728function addToArray(arr, index, value) { 55729 // perf: array.push is faster than array.splice! 55730 if (index >= arr.length) { 55731 arr.push(value); 55732 } else { 55733 arr.splice(index, 0, value); 55734 } 55735} 55736 55737function removeFromArray(arr, index) { 55738 // perf: array.pop is faster than array.splice! 55739 if (index >= arr.length - 1) { 55740 return arr.pop(); 55741 } else { 55742 return arr.splice(index, 1)[0]; 55743 } 55744} 55745 55746function newArray(size, value) { 55747 const list = []; 55748 55749 for (let i = 0; i < size; i++) { 55750 list.push(value); 55751 } 55752 55753 return list; 55754} 55755/** 55756 * Remove item from array (Same as `Array.splice()` but faster.) 55757 * 55758 * `Array.splice()` is not as fast because it has to allocate an array for the elements which were 55759 * removed. This causes memory pressure and slows down code when most of the time we don't 55760 * care about the deleted items array. 55761 * 55762 * https://jsperf.com/fast-array-splice (About 20x faster) 55763 * 55764 * @param array Array to splice 55765 * @param index Index of element in array to remove. 55766 * @param count Number of items to remove. 55767 */ 55768 55769 55770function arraySplice(array, index, count) { 55771 const length = array.length - count; 55772 55773 while (index < length) { 55774 array[index] = array[index + count]; 55775 index++; 55776 } 55777 55778 while (count--) { 55779 array.pop(); // shrink the array 55780 } 55781} 55782/** 55783 * Same as `Array.splice(index, 0, value)` but faster. 55784 * 55785 * `Array.splice()` is not fast because it has to allocate an array for the elements which were 55786 * removed. This causes memory pressure and slows down code when most of the time we don't 55787 * care about the deleted items array. 55788 * 55789 * @param array Array to splice. 55790 * @param index Index in array where the `value` should be added. 55791 * @param value Value to add to array. 55792 */ 55793 55794 55795function arrayInsert(array, index, value) { 55796 ngDevMode && assertLessThanOrEqual(index, array.length, 'Can\'t insert past array end.'); 55797 let end = array.length; 55798 55799 while (end > index) { 55800 const previousEnd = end - 1; 55801 array[end] = array[previousEnd]; 55802 end = previousEnd; 55803 } 55804 55805 array[index] = value; 55806} 55807/** 55808 * Same as `Array.splice2(index, 0, value1, value2)` but faster. 55809 * 55810 * `Array.splice()` is not fast because it has to allocate an array for the elements which were 55811 * removed. This causes memory pressure and slows down code when most of the time we don't 55812 * care about the deleted items array. 55813 * 55814 * @param array Array to splice. 55815 * @param index Index in array where the `value` should be added. 55816 * @param value1 Value to add to array. 55817 * @param value2 Value to add to array. 55818 */ 55819 55820 55821function arrayInsert2(array, index, value1, value2) { 55822 ngDevMode && assertLessThanOrEqual(index, array.length, 'Can\'t insert past array end.'); 55823 let end = array.length; 55824 55825 if (end == index) { 55826 // inserting at the end. 55827 array.push(value1, value2); 55828 } else if (end === 1) { 55829 // corner case when we have less items in array than we have items to insert. 55830 array.push(value2, array[0]); 55831 array[0] = value1; 55832 } else { 55833 end--; 55834 array.push(array[end - 1], array[end]); 55835 55836 while (end > index) { 55837 const previousEnd = end - 2; 55838 array[end] = array[previousEnd]; 55839 end--; 55840 } 55841 55842 array[index] = value1; 55843 array[index + 1] = value2; 55844 } 55845} 55846/** 55847 * Insert a `value` into an `array` so that the array remains sorted. 55848 * 55849 * NOTE: 55850 * - Duplicates are not allowed, and are ignored. 55851 * - This uses binary search algorithm for fast inserts. 55852 * 55853 * @param array A sorted array to insert into. 55854 * @param value The value to insert. 55855 * @returns index of the inserted value. 55856 */ 55857 55858 55859function arrayInsertSorted(array, value) { 55860 let index = arrayIndexOfSorted(array, value); 55861 55862 if (index < 0) { 55863 // if we did not find it insert it. 55864 index = ~index; 55865 arrayInsert(array, index, value); 55866 } 55867 55868 return index; 55869} 55870/** 55871 * Remove `value` from a sorted `array`. 55872 * 55873 * NOTE: 55874 * - This uses binary search algorithm for fast removals. 55875 * 55876 * @param array A sorted array to remove from. 55877 * @param value The value to remove. 55878 * @returns index of the removed value. 55879 * - positive index if value found and removed. 55880 * - negative index if value not found. (`~index` to get the value where it should have been 55881 * inserted) 55882 */ 55883 55884 55885function arrayRemoveSorted(array, value) { 55886 const index = arrayIndexOfSorted(array, value); 55887 55888 if (index >= 0) { 55889 arraySplice(array, index, 1); 55890 } 55891 55892 return index; 55893} 55894/** 55895 * Get an index of an `value` in a sorted `array`. 55896 * 55897 * NOTE: 55898 * - This uses binary search algorithm for fast removals. 55899 * 55900 * @param array A sorted array to binary search. 55901 * @param value The value to look for. 55902 * @returns index of the value. 55903 * - positive index if value found. 55904 * - negative index if value not found. (`~index` to get the value where it should have been 55905 * located) 55906 */ 55907 55908 55909function arrayIndexOfSorted(array, value) { 55910 return _arrayIndexOfSorted(array, value, 0); 55911} 55912/** 55913 * Set a `value` for a `key`. 55914 * 55915 * @param keyValueArray to modify. 55916 * @param key The key to locate or create. 55917 * @param value The value to set for a `key`. 55918 * @returns index (always even) of where the value vas set. 55919 */ 55920 55921 55922function keyValueArraySet(keyValueArray, key, value) { 55923 let index = keyValueArrayIndexOf(keyValueArray, key); 55924 55925 if (index >= 0) { 55926 // if we found it set it. 55927 keyValueArray[index | 1] = value; 55928 } else { 55929 index = ~index; 55930 arrayInsert2(keyValueArray, index, key, value); 55931 } 55932 55933 return index; 55934} 55935/** 55936 * Retrieve a `value` for a `key` (on `undefined` if not found.) 55937 * 55938 * @param keyValueArray to search. 55939 * @param key The key to locate. 55940 * @return The `value` stored at the `key` location or `undefined if not found. 55941 */ 55942 55943 55944function keyValueArrayGet(keyValueArray, key) { 55945 const index = keyValueArrayIndexOf(keyValueArray, key); 55946 55947 if (index >= 0) { 55948 // if we found it retrieve it. 55949 return keyValueArray[index | 1]; 55950 } 55951 55952 return undefined; 55953} 55954/** 55955 * Retrieve a `key` index value in the array or `-1` if not found. 55956 * 55957 * @param keyValueArray to search. 55958 * @param key The key to locate. 55959 * @returns index of where the key is (or should have been.) 55960 * - positive (even) index if key found. 55961 * - negative index if key not found. (`~index` (even) to get the index where it should have 55962 * been inserted.) 55963 */ 55964 55965 55966function keyValueArrayIndexOf(keyValueArray, key) { 55967 return _arrayIndexOfSorted(keyValueArray, key, 1); 55968} 55969/** 55970 * Delete a `key` (and `value`) from the `KeyValueArray`. 55971 * 55972 * @param keyValueArray to modify. 55973 * @param key The key to locate or delete (if exist). 55974 * @returns index of where the key was (or should have been.) 55975 * - positive (even) index if key found and deleted. 55976 * - negative index if key not found. (`~index` (even) to get the index where it should have 55977 * been.) 55978 */ 55979 55980 55981function keyValueArrayDelete(keyValueArray, key) { 55982 const index = keyValueArrayIndexOf(keyValueArray, key); 55983 55984 if (index >= 0) { 55985 // if we found it remove it. 55986 arraySplice(keyValueArray, index, 2); 55987 } 55988 55989 return index; 55990} 55991/** 55992 * INTERNAL: Get an index of an `value` in a sorted `array` by grouping search by `shift`. 55993 * 55994 * NOTE: 55995 * - This uses binary search algorithm for fast removals. 55996 * 55997 * @param array A sorted array to binary search. 55998 * @param value The value to look for. 55999 * @param shift grouping shift. 56000 * - `0` means look at every location 56001 * - `1` means only look at every other (even) location (the odd locations are to be ignored as 56002 * they are values.) 56003 * @returns index of the value. 56004 * - positive index if value found. 56005 * - negative index if value not found. (`~index` to get the value where it should have been 56006 * inserted) 56007 */ 56008 56009 56010function _arrayIndexOfSorted(array, value, shift) { 56011 ngDevMode && assertEqual(Array.isArray(array), true, 'Expecting an array'); 56012 let start = 0; 56013 let end = array.length >> shift; 56014 56015 while (end !== start) { 56016 const middle = start + (end - start >> 1); // find the middle. 56017 56018 const current = array[middle << shift]; 56019 56020 if (value === current) { 56021 return middle << shift; 56022 } else if (current > value) { 56023 end = middle; 56024 } else { 56025 start = middle + 1; // We already searched middle so make it non-inclusive by adding 1 56026 } 56027 } 56028 56029 return ~(end << shift); 56030} 56031/** 56032 * @license 56033 * Copyright Google LLC All Rights Reserved. 56034 * 56035 * Use of this source code is governed by an MIT-style license that can be 56036 * found in the LICENSE file at https://angular.io/license 56037 */ 56038 56039/* 56040 * ######################### 56041 * Attention: These Regular expressions have to hold even if the code is minified! 56042 * ########################## 56043 */ 56044 56045/** 56046 * Regular expression that detects pass-through constructors for ES5 output. This Regex 56047 * intends to capture the common delegation pattern emitted by TypeScript and Babel. Also 56048 * it intends to capture the pattern where existing constructors have been downleveled from 56049 * ES2015 to ES5 using TypeScript w/ downlevel iteration. e.g. 56050 * 56051 * ``` 56052 * function MyClass() { 56053 * var _this = _super.apply(this, arguments) || this; 56054 * ``` 56055 * 56056 * downleveled to ES5 with `downlevelIteration` for TypeScript < 4.2: 56057 * ``` 56058 * function MyClass() { 56059 * var _this = _super.apply(this, __spread(arguments)) || this; 56060 * ``` 56061 * 56062 * or downleveled to ES5 with `downlevelIteration` for TypeScript >= 4.2: 56063 * ``` 56064 * function MyClass() { 56065 * var _this = _super.apply(this, __spreadArray([], __read(arguments), false)) || this; 56066 * ``` 56067 * 56068 * More details can be found in: https://github.com/angular/angular/issues/38453. 56069 */ 56070 56071 56072const ES5_DELEGATE_CTOR = /^function\s+\S+\(\)\s*{[\s\S]+\.apply\(this,\s*(arguments|(?:[^()]+\(\[\],)?[^()]+\(arguments\).*)\)/; 56073/** Regular expression that detects ES2015 classes which extend from other classes. */ 56074 56075const ES2015_INHERITED_CLASS = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{/; 56076/** 56077 * Regular expression that detects ES2015 classes which extend from other classes and 56078 * have an explicit constructor defined. 56079 */ 56080 56081const ES2015_INHERITED_CLASS_WITH_CTOR = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{[\s\S]*constructor\s*\(/; 56082/** 56083 * Regular expression that detects ES2015 classes which extend from other classes 56084 * and inherit a constructor. 56085 */ 56086 56087const ES2015_INHERITED_CLASS_WITH_DELEGATE_CTOR = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{[\s\S]*constructor\s*\(\)\s*{[^}]*super\(\.\.\.arguments\)/; 56088/** 56089 * Determine whether a stringified type is a class which delegates its constructor 56090 * to its parent. 56091 * 56092 * This is not trivial since compiled code can actually contain a constructor function 56093 * even if the original source code did not. For instance, when the child class contains 56094 * an initialized instance property. 56095 */ 56096 56097function isDelegateCtor(typeStr) { 56098 return ES5_DELEGATE_CTOR.test(typeStr) || ES2015_INHERITED_CLASS_WITH_DELEGATE_CTOR.test(typeStr) || ES2015_INHERITED_CLASS.test(typeStr) && !ES2015_INHERITED_CLASS_WITH_CTOR.test(typeStr); 56099} 56100 56101class ReflectionCapabilities { 56102 constructor(reflect) { 56103 this._reflect = reflect || _global['Reflect']; 56104 } 56105 56106 factory(t) { 56107 return (...args) => new t(...args); 56108 } 56109 /** @internal */ 56110 56111 56112 _zipTypesAndAnnotations(paramTypes, paramAnnotations) { 56113 let result; 56114 56115 if (typeof paramTypes === 'undefined') { 56116 result = newArray(paramAnnotations.length); 56117 } else { 56118 result = newArray(paramTypes.length); 56119 } 56120 56121 for (let i = 0; i < result.length; i++) { 56122 // TS outputs Object for parameters without types, while Traceur omits 56123 // the annotations. For now we preserve the Traceur behavior to aid 56124 // migration, but this can be revisited. 56125 if (typeof paramTypes === 'undefined') { 56126 result[i] = []; 56127 } else if (paramTypes[i] && paramTypes[i] != Object) { 56128 result[i] = [paramTypes[i]]; 56129 } else { 56130 result[i] = []; 56131 } 56132 56133 if (paramAnnotations && paramAnnotations[i] != null) { 56134 result[i] = result[i].concat(paramAnnotations[i]); 56135 } 56136 } 56137 56138 return result; 56139 } 56140 56141 _ownParameters(type, parentCtor) { 56142 const typeStr = type.toString(); // If we have no decorators, we only have function.length as metadata. 56143 // In that case, to detect whether a child class declared an own constructor or not, 56144 // we need to look inside of that constructor to check whether it is 56145 // just calling the parent. 56146 // This also helps to work around for https://github.com/Microsoft/TypeScript/issues/12439 56147 // that sets 'design:paramtypes' to [] 56148 // if a class inherits from another class but has no ctor declared itself. 56149 56150 if (isDelegateCtor(typeStr)) { 56151 return null; 56152 } // Prefer the direct API. 56153 56154 56155 if (type.parameters && type.parameters !== parentCtor.parameters) { 56156 return type.parameters; 56157 } // API of tsickle for lowering decorators to properties on the class. 56158 56159 56160 const tsickleCtorParams = type.ctorParameters; 56161 56162 if (tsickleCtorParams && tsickleCtorParams !== parentCtor.ctorParameters) { 56163 // Newer tsickle uses a function closure 56164 // Retain the non-function case for compatibility with older tsickle 56165 const ctorParameters = typeof tsickleCtorParams === 'function' ? tsickleCtorParams() : tsickleCtorParams; 56166 const paramTypes = ctorParameters.map(ctorParam => ctorParam && ctorParam.type); 56167 const paramAnnotations = ctorParameters.map(ctorParam => ctorParam && convertTsickleDecoratorIntoMetadata(ctorParam.decorators)); 56168 return this._zipTypesAndAnnotations(paramTypes, paramAnnotations); 56169 } // API for metadata created by invoking the decorators. 56170 56171 56172 const paramAnnotations = type.hasOwnProperty(PARAMETERS) && type[PARAMETERS]; 56173 56174 const paramTypes = this._reflect && this._reflect.getOwnMetadata && this._reflect.getOwnMetadata('design:paramtypes', type); 56175 56176 if (paramTypes || paramAnnotations) { 56177 return this._zipTypesAndAnnotations(paramTypes, paramAnnotations); 56178 } // If a class has no decorators, at least create metadata 56179 // based on function.length. 56180 // Note: We know that this is a real constructor as we checked 56181 // the content of the constructor above. 56182 56183 56184 return newArray(type.length); 56185 } 56186 56187 parameters(type) { 56188 // Note: only report metadata if we have at least one class decorator 56189 // to stay in sync with the static reflector. 56190 if (!isType(type)) { 56191 return []; 56192 } 56193 56194 const parentCtor = getParentCtor(type); 56195 56196 let parameters = this._ownParameters(type, parentCtor); 56197 56198 if (!parameters && parentCtor !== Object) { 56199 parameters = this.parameters(parentCtor); 56200 } 56201 56202 return parameters || []; 56203 } 56204 56205 _ownAnnotations(typeOrFunc, parentCtor) { 56206 // Prefer the direct API. 56207 if (typeOrFunc.annotations && typeOrFunc.annotations !== parentCtor.annotations) { 56208 let annotations = typeOrFunc.annotations; 56209 56210 if (typeof annotations === 'function' && annotations.annotations) { 56211 annotations = annotations.annotations; 56212 } 56213 56214 return annotations; 56215 } // API of tsickle for lowering decorators to properties on the class. 56216 56217 56218 if (typeOrFunc.decorators && typeOrFunc.decorators !== parentCtor.decorators) { 56219 return convertTsickleDecoratorIntoMetadata(typeOrFunc.decorators); 56220 } // API for metadata created by invoking the decorators. 56221 56222 56223 if (typeOrFunc.hasOwnProperty(ANNOTATIONS)) { 56224 return typeOrFunc[ANNOTATIONS]; 56225 } 56226 56227 return null; 56228 } 56229 56230 annotations(typeOrFunc) { 56231 if (!isType(typeOrFunc)) { 56232 return []; 56233 } 56234 56235 const parentCtor = getParentCtor(typeOrFunc); 56236 const ownAnnotations = this._ownAnnotations(typeOrFunc, parentCtor) || []; 56237 const parentAnnotations = parentCtor !== Object ? this.annotations(parentCtor) : []; 56238 return parentAnnotations.concat(ownAnnotations); 56239 } 56240 56241 _ownPropMetadata(typeOrFunc, parentCtor) { 56242 // Prefer the direct API. 56243 if (typeOrFunc.propMetadata && typeOrFunc.propMetadata !== parentCtor.propMetadata) { 56244 let propMetadata = typeOrFunc.propMetadata; 56245 56246 if (typeof propMetadata === 'function' && propMetadata.propMetadata) { 56247 propMetadata = propMetadata.propMetadata; 56248 } 56249 56250 return propMetadata; 56251 } // API of tsickle for lowering decorators to properties on the class. 56252 56253 56254 if (typeOrFunc.propDecorators && typeOrFunc.propDecorators !== parentCtor.propDecorators) { 56255 const propDecorators = typeOrFunc.propDecorators; 56256 const propMetadata = {}; 56257 Object.keys(propDecorators).forEach(prop => { 56258 propMetadata[prop] = convertTsickleDecoratorIntoMetadata(propDecorators[prop]); 56259 }); 56260 return propMetadata; 56261 } // API for metadata created by invoking the decorators. 56262 56263 56264 if (typeOrFunc.hasOwnProperty(PROP_METADATA)) { 56265 return typeOrFunc[PROP_METADATA]; 56266 } 56267 56268 return null; 56269 } 56270 56271 propMetadata(typeOrFunc) { 56272 if (!isType(typeOrFunc)) { 56273 return {}; 56274 } 56275 56276 const parentCtor = getParentCtor(typeOrFunc); 56277 const propMetadata = {}; 56278 56279 if (parentCtor !== Object) { 56280 const parentPropMetadata = this.propMetadata(parentCtor);
56281 Object.keys(parentPropMetadata).forEach(propName => { 56282 propMetadata[propName] = parentPropMetadata[propName]; 56283 }); 56284 } 56285 56286 const ownPropMetadata = this._ownPropMetadata(typeOrFunc, parentCtor); 56287 56288 if (ownPropMetadata) { 56289 Object.keys(ownPropMetadata).forEach(propName => { 56290 const decorators = []; 56291 56292 if (propMetadata.hasOwnProperty(propName)) { 56293 decorators.push(...propMetadata[propName]); 56294 } 56295 56296 decorators.push(...ownPropMetadata[propName]); 56297 propMetadata[propName] = decorators; 56298 }); 56299 } 56300 56301 return propMetadata; 56302 } 56303 56304 ownPropMetadata(typeOrFunc) { 56305 if (!isType(typeOrFunc)) { 56306 return {}; 56307 } 56308 56309 return this._ownPropMetadata(typeOrFunc, getParentCtor(typeOrFunc)) || {}; 56310 } 56311 56312 hasLifecycleHook(type, lcProperty) { 56313 return type instanceof Type && lcProperty in type.prototype; 56314 } 56315 56316} 56317 56318function convertTsickleDecoratorIntoMetadata(decoratorInvocations) { 56319 if (!decoratorInvocations) { 56320 return []; 56321 } 56322 56323 return decoratorInvocations.map(decoratorInvocation => { 56324 const decoratorType = decoratorInvocation.type; 56325 const annotationCls = decoratorType.annotationCls; 56326 const annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : []; 56327 return new annotationCls(...annotationArgs); 56328 }); 56329} 56330 56331function getParentCtor(ctor) { 56332 const parentProto = ctor.prototype ? Object.getPrototypeOf(ctor.prototype) : null; 56333 const parentCtor = parentProto ? parentProto.constructor : null; // Note: We always use `Object` as the null value 56334 // to simplify checking later on. 56335 56336 return parentCtor || Object; 56337} 56338/** 56339 * @license 56340 * Copyright Google LLC All Rights Reserved. 56341 * 56342 * Use of this source code is governed by an MIT-style license that can be 56343 * found in the LICENSE file at https://angular.io/license 56344 */ 56345 56346 56347const _THROW_IF_NOT_FOUND = {}; 56348const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND; 56349/* 56350 * Name of a property (that we patch onto DI decorator), which is used as an annotation of which 56351 * InjectFlag this decorator represents. This allows to avoid direct references to the DI decorators 56352 * in the code, thus making them tree-shakable. 56353 */ 56354 56355const DI_DECORATOR_FLAG = '__NG_DI_FLAG__'; 56356const NG_TEMP_TOKEN_PATH = 'ngTempTokenPath'; 56357const NG_TOKEN_PATH = 'ngTokenPath'; 56358const NEW_LINE = /\n/gm; 56359const NO_NEW_LINE = 'ɵ'; 56360const SOURCE = '__source'; 56361/** 56362 * Current injector value used by `inject`. 56363 * - `undefined`: it is an error to call `inject` 56364 * - `null`: `inject` can be called but there is no injector (limp-mode). 56365 * - Injector instance: Use the injector for resolution. 56366 */ 56367 56368let _currentInjector = undefined; 56369 56370function setCurrentInjector(injector) { 56371 const former = _currentInjector; 56372 _currentInjector = injector; 56373 return former; 56374} 56375 56376function injectInjectorOnly(token, flags = InjectFlags.Default) { 56377 if (_currentInjector === undefined) { 56378 throw new RuntimeError(-203 56379 /* RuntimeErrorCode.MISSING_INJECTION_CONTEXT */ 56380 , ngDevMode && `inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with \`EnvironmentInjector#runInContext\`.`); 56381 } else if (_currentInjector === null) { 56382 return injectRootLimpMode(token, undefined, flags); 56383 } else { 56384 return _currentInjector.get(token, flags & InjectFlags.Optional ? null : undefined, flags); 56385 } 56386} 56387 56388function ɵɵinject(token, flags = InjectFlags.Default) { 56389 return (getInjectImplementation() || injectInjectorOnly)(resolveForwardRef(token), flags); 56390} 56391/** 56392 * Throws an error indicating that a factory function could not be generated by the compiler for a 56393 * particular class. 56394 * 56395 * The name of the class is not mentioned here, but will be in the generated factory function name 56396 * and thus in the stack trace. 56397 * 56398 * @codeGenApi 56399 */ 56400 56401 56402function ɵɵinvalidFactoryDep(index) { 56403 throw new RuntimeError(202 56404 /* RuntimeErrorCode.INVALID_FACTORY_DEPENDENCY */ 56405 , ngDevMode && `This constructor is not compatible with Angular Dependency Injection because its dependency at index ${index} of the parameter list is invalid. 56406This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator. 56407 56408Please check that 1) the type for the parameter at index ${index} is correct and 2) the correct Angular decorators are defined for this class and its ancestors.`); 56409} 56410/** 56411 * Injects a token from the currently active injector. 56412 * `inject` is only supported during instantiation of a dependency by the DI system. It can be used 56413 * during: 56414 * - Construction (via the `constructor`) of a class being instantiated by the DI system, such 56415 * as an `@Injectable` or `@Component`. 56416 * - In the initializer for fields of such classes. 56417 * - In the factory function specified for `useFactory` of a `Provider` or an `@Injectable`. 56418 * - In the `factory` function specified for an `InjectionToken`. 56419 * 56420 * @param token A token that represents a dependency that should be injected. 56421 * @param flags Optional flags that control how injection is executed. 56422 * The flags correspond to injection strategies that can be specified with 56423 * parameter decorators `@Host`, `@Self`, `@SkipSef`, and `@Optional`. 56424 * @returns the injected value if operation is successful, `null` otherwise. 56425 * @throws if called outside of a supported context. 56426 * 56427 * @usageNotes 56428 * In practice the `inject()` calls are allowed in a constructor, a constructor parameter and a 56429 * field initializer: 56430 * 56431 * ```typescript 56432 * @Injectable({providedIn: 'root'}) 56433 * export class Car { 56434 * radio: Radio|undefined; 56435 * // OK: field initializer 56436 * spareTyre = inject(Tyre); 56437 * 56438 * constructor() { 56439 * // OK: constructor body 56440 * this.radio = inject(Radio); 56441 * } 56442 * } 56443 * ``` 56444 * 56445 * It is also legal to call `inject` from a provider's factory: 56446 * 56447 * ```typescript 56448 * providers: [ 56449 * {provide: Car, useFactory: () => { 56450 * // OK: a class factory 56451 * const engine = inject(Engine); 56452 * return new Car(engine); 56453 * }} 56454 * ] 56455 * ``` 56456 * 56457 * Calls to the `inject()` function outside of the class creation context will result in error. Most 56458 * notably, calls to `inject()` are disallowed after a class instance was created, in methods 56459 * (including lifecycle hooks): 56460 * 56461 * ```typescript 56462 * @Component({ ... }) 56463 * export class CarComponent { 56464 * ngOnInit() { 56465 * // ERROR: too late, the component instance was already created 56466 * const engine = inject(Engine); 56467 * engine.start(); 56468 * } 56469 * } 56470 * ``` 56471 * 56472 * @publicApi 56473 */ 56474 56475 56476function inject(token, flags = InjectFlags.Default) { 56477 if (typeof flags !== 'number') {
vendor: 5,697 bytes, lines 56478-56687
56478 // While TypeScript doesn't accept it without a cast, bitwise OR with false-y values in 56479 // JavaScript is a no-op. We can use that for a very codesize-efficient conversion from 56480 // `InjectOptions` to `InjectFlags`. 56481 flags = 0 56482 /* InternalInjectFlags.Default */ 56483 | ( // comment to force a line break in the formatter 56484 flags.optional && 8 56485 /* InternalInjectFlags.Optional */ 56486 ) | (flags.host && 1 56487 /* InternalInjectFlags.Host */ 56488 ) | (flags.self && 2 56489 /* InternalInjectFlags.Self */ 56490 ) | (flags.skipSelf && 4 56491 /* InternalInjectFlags.SkipSelf */ 56492 ); 56493 } 56494 56495 return ɵɵinject(token, flags); 56496} 56497 56498function injectArgs(types) { 56499 const args = []; 56500 56501 for (let i = 0; i < types.length; i++) { 56502 const arg = resolveForwardRef(types[i]); 56503 56504 if (Array.isArray(arg)) { 56505 if (arg.length === 0) { 56506 throw new RuntimeError(900 56507 /* RuntimeErrorCode.INVALID_DIFFER_INPUT */ 56508 , ngDevMode && 'Arguments array must have arguments.'); 56509 } 56510 56511 let type = undefined; 56512 let flags = InjectFlags.Default; 56513 56514 for (let j = 0; j < arg.length; j++) { 56515 const meta = arg[j]; 56516 const flag = getInjectFlag(meta); 56517 56518 if (typeof flag === 'number') { 56519 // Special case when we handle @Inject decorator. 56520 if (flag === -1 56521 /* DecoratorFlags.Inject */ 56522 ) { 56523 type = meta.token; 56524 } else { 56525 flags |= flag; 56526 } 56527 } else { 56528 type = meta; 56529 } 56530 } 56531 56532 args.push(ɵɵinject(type, flags)); 56533 } else { 56534 args.push(ɵɵinject(arg)); 56535 } 56536 } 56537 56538 return args; 56539} 56540/** 56541 * Attaches a given InjectFlag to a given decorator using monkey-patching. 56542 * Since DI decorators can be used in providers `deps` array (when provider is configured using 56543 * `useFactory`) without initialization (e.g. `Host`) and as an instance (e.g. `new Host()`), we 56544 * attach the flag to make it available both as a static property and as a field on decorator 56545 * instance. 56546 * 56547 * @param decorator Provided DI decorator. 56548 * @param flag InjectFlag that should be applied. 56549 */ 56550 56551 56552function attachInjectFlag(decorator, flag) { 56553 decorator[DI_DECORATOR_FLAG] = flag; 56554 decorator.prototype[DI_DECORATOR_FLAG] = flag; 56555 return decorator; 56556} 56557/** 56558 * Reads monkey-patched property that contains InjectFlag attached to a decorator. 56559 * 56560 * @param token Token that may contain monkey-patched DI flags property. 56561 */ 56562 56563 56564function getInjectFlag(token) { 56565 return token[DI_DECORATOR_FLAG]; 56566} 56567 56568function catchInjectorError(e, token, injectorErrorName, source) { 56569 const tokenPath = e[NG_TEMP_TOKEN_PATH]; 56570 56571 if (token[SOURCE]) { 56572 tokenPath.unshift(token[SOURCE]); 56573 } 56574 56575 e.message = formatError('\n' + e.message, tokenPath, injectorErrorName, source); 56576 e[NG_TOKEN_PATH] = tokenPath; 56577 e[NG_TEMP_TOKEN_PATH] = null; 56578 throw e; 56579} 56580 56581function formatError(text, obj, injectorErrorName, source = null) { 56582 text = text && text.charAt(0) === '\n' && text.charAt(1) == NO_NEW_LINE ? text.slice(2) : text; 56583 let context = stringify(obj); 56584 56585 if (Array.isArray(obj)) { 56586 context = obj.map(stringify).join(' -> '); 56587 } else if (typeof obj === 'object') { 56588 let parts = []; 56589 56590 for (let key in obj) { 56591 if (obj.hasOwnProperty(key)) { 56592 let value = obj[key]; 56593 parts.push(key + ':' + (typeof value === 'string' ? JSON.stringify(value) : stringify(value))); 56594 } 56595 } 56596 56597 context = `{${parts.join(', ')}}`; 56598 } 56599 56600 return `${injectorErrorName}${source ? '(' + source + ')' : ''}[${context}]: ${text.replace(NEW_LINE, '\n ')}`; 56601} 56602/** 56603 * @license 56604 * Copyright Google LLC All Rights Reserved. 56605 * 56606 * Use of this source code is governed by an MIT-style license that can be 56607 * found in the LICENSE file at https://angular.io/license 56608 */ 56609 56610/** 56611 * Inject decorator and metadata. 56612 * 56613 * @Annotation 56614 * @publicApi 56615 */ 56616 56617 56618const Inject = attachInjectFlag( // Disable tslint because `DecoratorFlags` is a const enum which gets inlined. 56619// tslint:disable-next-line: no-toplevel-property-access 56620makeParamDecorator('Inject', token => ({ 56621 token 56622})), -1 56623/* DecoratorFlags.Inject */ 56624); 56625/** 56626 * Optional decorator and metadata. 56627 * 56628 * @Annotation 56629 * @publicApi 56630 */ 56631 56632const Optional = // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined. 56633// tslint:disable-next-line: no-toplevel-property-access 56634attachInjectFlag(makeParamDecorator('Optional'), 8 56635/* InternalInjectFlags.Optional */ 56636); 56637/** 56638 * Self decorator and metadata. 56639 * 56640 * @Annotation 56641 * @publicApi 56642 */ 56643 56644const Self = // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined. 56645// tslint:disable-next-line: no-toplevel-property-access 56646attachInjectFlag(makeParamDecorator('Self'), 2 56647/* InternalInjectFlags.Self */ 56648); 56649/** 56650 * `SkipSelf` decorator and metadata. 56651 * 56652 * @Annotation 56653 * @publicApi 56654 */ 56655 56656const SkipSelf = // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined. 56657// tslint:disable-next-line: no-toplevel-property-access 56658attachInjectFlag(makeParamDecorator('SkipSelf'), 4 56659/* InternalInjectFlags.SkipSelf */ 56660); 56661/** 56662 * Host decorator and metadata. 56663 * 56664 * @Annotation 56665 * @publicApi 56666 */ 56667 56668const Host = // Disable tslint because `InternalInjectFlags` is a const enum which gets inlined. 56669// tslint:disable-next-line: no-toplevel-property-access 56670attachInjectFlag(makeParamDecorator('Host'), 1 56671/* InternalInjectFlags.Host */ 56672); 56673/** 56674 * @license 56675 * Copyright Google LLC All Rights Reserved. 56676 * 56677 * Use of this source code is governed by an MIT-style license that can be 56678 * found in the LICENSE file at https://angular.io/license 56679 */ 56680 56681let _reflect = null; 56682 56683function getReflect() { 56684 return _reflect = _reflect || new ReflectionCapabilities(); 56685} 56686 56687function reflectDependencies(type) {
56688 return convertDependencies(getReflect().parameters(type)); 56689} 56690 56691function convertDependencies(deps) { 56692 return deps.map(dep => reflectDependency(dep)); 56693} 56694 56695function reflectDependency(dep) { 56696 const meta = { 56697 token: null, 56698 attribute: null, 56699 host: false, 56700 optional: false, 56701 self: false, 56702 skipSelf: false 56703 }; 56704 56705 if (Array.isArray(dep) && dep.length > 0) { 56706 for (let j = 0; j < dep.length; j++) { 56707 const param = dep[j]; 56708 56709 if (param === undefined) { 56710 // param may be undefined if type of dep is not set by ngtsc 56711 continue; 56712 } 56713 56714 const proto = Object.getPrototypeOf(param); 56715 56716 if (param instanceof Optional || proto.ngMetadataName === 'Optional') { 56717 meta.optional = true; 56718 } else if (param instanceof SkipSelf || proto.ngMetadataName === 'SkipSelf') { 56719 meta.skipSelf = true; 56720 } else if (param instanceof Self || proto.ngMetadataName === 'Self') { 56721 meta.self = true; 56722 } else if (param instanceof Host || proto.ngMetadataName === 'Host') { 56723 meta.host = true; 56724 } else if (param instanceof Inject) { 56725 meta.token = param.token; 56726 } else if (param instanceof Attribute) { 56727 if (param.attributeName === undefined) { 56728 throw new RuntimeError(204 56729 /* RuntimeErrorCode.INVALID_INJECTION_TOKEN */ 56730 , ngDevMode && `Attribute name must be defined.`); 56731 } 56732 56733 meta.attribute = param.attributeName; 56734 } else { 56735 meta.token = param; 56736 } 56737 } 56738 } else if (dep === undefined || Array.isArray(dep) && dep.length === 0) { 56739 meta.token = null; 56740 } else { 56741 meta.token = dep; 56742 } 56743 56744 return meta; 56745} 56746/** 56747 * @license 56748 * Copyright Google LLC All Rights Reserved. 56749 * 56750 * Use of this source code is governed by an MIT-style license that can be 56751 * found in the LICENSE file at https://angular.io/license 56752 */ 56753 56754/** 56755 * Used to resolve resource URLs on `@Component` when used with JIT compilation. 56756 * 56757 * Example: 56758 * ``` 56759 * @Component({ 56760 * selector: 'my-comp', 56761 * templateUrl: 'my-comp.html', // This requires asynchronous resolution 56762 * }) 56763 * class MyComponent{ 56764 * } 56765 * 56766 * // Calling `renderComponent` will fail because `renderComponent` is a synchronous process 56767 * // and `MyComponent`'s `@Component.templateUrl` needs to be resolved asynchronously. 56768 * 56769 * // Calling `resolveComponentResources()` will resolve `@Component.templateUrl` into 56770 * // `@Component.template`, which allows `renderComponent` to proceed in a synchronous manner. 56771 * 56772 * // Use browser's `fetch()` function as the default resource resolution strategy. 56773 * resolveComponentResources(fetch).then(() => { 56774 * // After resolution all URLs have been converted into `template` strings. 56775 * renderComponent(MyComponent); 56776 * }); 56777 * 56778 * ``` 56779 * 56780 * NOTE: In AOT the resolution happens during compilation, and so there should be no need 56781 * to call this method outside JIT mode. 56782 * 56783 * @param resourceResolver a function which is responsible for returning a `Promise` to the 56784 * contents of the resolved URL. Browser's `fetch()` method is a good default implementation. 56785 */ 56786 56787 56788function resolveComponentResources(resourceResolver) { 56789 // Store all promises which are fetching the resources. 56790 const componentResolved = []; // Cache so that we don't fetch the same resource more than once. 56791 56792 const urlMap = new Map(); 56793 56794 function cachedResourceResolve(url) { 56795 let promise = urlMap.get(url); 56796 56797 if (!promise) { 56798 const resp = resourceResolver(url); 56799 urlMap.set(url, promise = resp.then(unwrapResponse)); 56800 } 56801 56802 return promise; 56803 } 56804 56805 componentResourceResolutionQueue.forEach((component, type) => { 56806 const promises = []; 56807 56808 if (component.templateUrl) { 56809 promises.push(cachedResourceResolve(component.templateUrl).then(template => { 56810 component.template = template; 56811 })); 56812 } 56813 56814 const styleUrls = component.styleUrls; 56815 const styles = component.styles || (component.styles = []); 56816 const styleOffset = component.styles.length; 56817 styleUrls && styleUrls.forEach((styleUrl, index) => { 56818 styles.push(''); // pre-allocate array. 56819 56820 promises.push(cachedResourceResolve(styleUrl).then(style => { 56821 styles[styleOffset + index] = style; 56822 styleUrls.splice(styleUrls.indexOf(styleUrl), 1); 56823 56824 if (styleUrls.length == 0) { 56825 component.styleUrls = undefined; 56826 } 56827 })); 56828 }); 56829 const fullyResolved = Promise.all(promises).then(() =>
56829 componentDefResolved(type)); 56830 componentResolved.push(fullyResolved); 56831 }); 56832 clearResolutionOfComponentResourcesQueue(); 56833 return Promise.all(componentResolved).then(() => undefined); 56834} 56835 56836let componentResourceResolutionQueue = new Map(); // Track when existing ɵcmp for a Type is waiting on resources. 56837 56838const componentDefPendingResolution = new Set(); 56839 56840function maybeQueueResolutionOfComponentResources(type, metadata) { 56841 if (componentNeedsResolution(metadata)) { 56842 componentResourceResolutionQueue.set(type, metadata); 56843 componentDefPendingResolution.add(type); 56844 } 56845} 56846 56847function isComponentDefPendingResolution(type) { 56848 return componentDefPendingResolution.has(type); 56849} 56850 56851function componentNeedsResolution(component) { 56852 return !!(component.templateUrl && !component.hasOwnProperty('template') || component.styleUrls && component.styleUrls.length); 56853} 56854 56855function clearResolutionOfComponentResourcesQueue() { 56856 const old = componentResourceResolutionQueue; 56857 componentResourceResolutionQueue = new Map(); 56858 return old; 56859} 56860 56861function restoreComponentResolutionQueue(queue) { 56862 componentDefPendingResolution.clear(); 56863 queue.forEach((_, type) => componentDefPendingResolution.add(type)); 56864 componentResourceResolutionQueue = queue; 56865} 56866 56867function isComponentResourceResolutionQueueEmpty() { 56868 return componentResourceResolutionQueue.size === 0; 56869} 56870 56871function unwrapResponse(response) { 56872 return typeof response == 'string' ? response : response.text(); 56873} 56874 56875function componentDefResolved(type) { 56876 componentDefPendingResolution.delete(type); 56877} 56878/** 56879 * @license 56880 * Copyright Google LLC All Rights Reserved. 56881 * 56882 * Use of this source code is governed by an MIT-style license that can be 56883 * found in the LICENSE file at https://angular.io/license 56884 */ 56885 56886/** 56887 * Map of module-id to the corresponding NgModule. 56888 */ 56889 56890 56891const modules = new Map(); 56892/** 56893 * Whether to check for duplicate NgModule registrations. 56894 * 56895 * This can be disabled for testing. 56896 */ 56897 56898let checkForDuplicateNgModules = true; 56899 56900function assertSameOrNotExisting(id, type, incoming) { 56901 if (type && type !== incoming && checkForDuplicateNgModules) { 56902 throw new Error(`Duplicate module registered for ${id} - ${stringify(type)} vs ${stringify(type.name)}`); 56903 } 56904} 56905/** 56906 * Adds the given NgModule type to Angular's NgModule registry. 56907 * 56908 * This is generated as a side-effect of NgModule compilation. Note that the `id` is passed in 56909 * explicitly and not read from the NgModule definition. This is for two reasons: it avoids a 56910 * megamorphic read, and in JIT there's a chicken-and-egg problem where the NgModule may not be 56911 * fully resolved when it's registered. 56912 * 56913 * @codeGenApi 56914 */ 56915 56916 56917function registerNgModuleType(ngModuleType, id) { 56918 const existing = modules.get(id) || null; 56919 assertSameOrNotExisting(id, existing, ngModuleType); 56920 modules.set(id, ngModuleType); 56921} 56922 56923function clearModulesForTest() { 56924 modules.clear(); 56925} 56926 56927function getRegisteredNgModuleType(id) { 56928 return modules.get(id); 56929} 56930/** 56931 * Control whether the NgModule registration system enforces that each NgModule type registered has 56932 * a unique id. 56933 * 56934 * This is useful for testing as the NgModule registry cannot be properly reset between tests with 56935 * Angular's current API. 56936 */ 56937 56938 56939function setAllowDuplicateNgModuleIdsForTest(allowDuplicates) { 56940 checkForDuplicateNgModules = !allowDuplicates; 56941} 56942/** 56943 * @license 56944 * Copyright Google LLC All Rights Reserved. 56945 * 56946 * Use of this source code is governed by an MIT-style license that can be 56947 * found in the LICENSE file at https://angular.io/license 56948 */ 56949 56950/** 56951 * Most of the use of `document` in Angular is from within the DI system so it is possible to simply 56952 * inject the `DOCUMENT` token and are done. 56953 * 56954 * Ivy is special because it does not rely upon the DI and must get hold of the document some other 56955 * way. 56956 * 56957 * The solution is to define `getDocument()` and `setDocument()` top-level functions for ivy. 56958 * Wherever ivy needs the global document, it calls `getDocument()` instead. 56959 * 56960 * When running ivy outside of a browser environment, it is necessary to call `setDocument()` to 56961 * tell ivy what the global `document` is. 56962 * 56963 * Angular does this for us in each of the standard platforms (`Browser`, `Server`, and `WebWorker`) 56964 * by calling `setDocument()` when providing the `DOCUMENT` token. 56965 */ 56966 56967 56968let DOCUMENT = undefined; 56969/** 56970 * Tell ivy what the `document` is for this platform. 56971 * 56972 * It is only necessary to call this if the current platform is not a browser. 56973 * 56974 * @param document The object representing the global `document` in this environment. 56975 */ 56976 56977function setDocument(document) { 56978 DOCUMENT = document; 56979} 56980/** 56981 * Access the object that represents the `document` for this platform. 56982 * 56983 * Ivy calls this whenever it needs to access the `document` object. 56984 * For example to create the renderer or to do sanitization. 56985 */ 56986 56987 56988function getDocument() { 56989 if (DOCUMENT !== undefined) { 56990 return DOCUMENT; 56991 } else if (typeof document !== 'undefined') { 56992 return document; 56993 } // No "document" can be found. This should only happen if we are running iv
56993y outside Angular and 56994 // the current platform is not a browser. Since this is not a supported scenario at the moment 56995 // this should not happen in Angular apps. 56996 // Once we support running ivy outside of Angular we will need to publish `setDocument()` as a 56997 // public API. Meanwhile we just return `undefined` and let the application fail. 56998 56999 57000 return undefined; 57001} 57002/** 57003 * @license 57004 * Copyright Google LLC All Rights Reserved. 57005 * 57006 * Use of this source code is governed by an MIT-style license that can be 57007 * found in the LICENSE file at https://angular.io/license 57008 */ 57009 57010/** 57011 * The Trusted Types policy, or null if Trusted Types are not 57012 * enabled/supported, or undefined if the policy has not been created yet. 57013 */ 57014 57015 57016let policy$1; 57017/** 57018 * Returns the Trusted Types policy, or null if Trusted Types are not 57019 * enabled/supported. The first call to this function will create the policy. 57020 */ 57021 57022function getPolicy$1() { 57023 if (policy$1 === undefined) { 57024 policy$1 = null; 57025 57026 if (_global.trustedTypes) { 57027 try { 57028 policy$1 = _global.trustedTypes.createPolicy('angular', { 57029 createHTML: s => s, 57030 createScript: s => s, 57031 createScriptURL: s => s 57032 }); 57033 } catch {// trustedTypes.createPolicy throws if called with a name that is 57034 // already registered, even in report-only mode. Until the API changes, 57035 // catch the error not to break the applications functionally. In such 57036 // cases, the code will fall back to using strings. 57037 } 57038 } 57039 } 57040 57041 return policy$1; 57042} 57043/** 57044 * Unsafely promote a string to a TrustedHTML, falling back to strings when 57045 * Trusted Types are not available. 57046 * @security This is a security-sensitive function; any use of this function 57047 * must go through security review. In particular, it must be assured that the 57048 * provided string will never cause an XSS vulnerability if used in a context 57049 * that will be interpreted as HTML by a browser, e.g. when assigning to 57050 * element.innerHTML. 57051 */ 57052 57053 57054function trustedHTMLFromString(html) { 57055 return getPolicy$1()?.createHTML(html) || html; 57056} 57057/** 57058 * Unsafely promote a string to a TrustedScript, falling back to strings when 57059 * Trusted Types are not available. 57060 * @security In particular, it must be assured that the provided string will 57061 * never cause an XSS vulnerability if used in a context that will be 57062 * interpreted and executed as a script by a browser, e.g. when calling eval. 57063 */ 57064 57065 57066function trustedScriptFromString(script) { 57067 return getPolicy$1()?.createScript(script) || script; 57068} 57069/** 57070 * Unsafely promote a string to a TrustedScriptURL, falling back to strings 57071 * when Trusted Types are not available. 57072 * @security This is a security-sensitive function; any use of this function 57073 * must go through security review. In particular, it must be assured that the 57074 * provided string will never cause an XSS vulnerability if used in a context 57075 * that will cause a browser to load and execute a resource, e.g. when 57076 * assigning to script.src. 57077 */ 57078 57079 57080function trustedScriptURLFromString(url) { 57081 return getPolicy$1()?.createScriptURL(url) || url; 57082} 57083/** 57084 * Unsafely call the Function constructor with the given string arguments. It 57085 * is only available in development mode, and should be stripped out of 57086 * production code. 57087 * @security This is a security-sensitive function; any use of this function 57088 * must go through security review. In particular, it must be assured that it 57089 * is only called from development code, as use in production code can lead to 57090 * XSS vulnerabilities. 57091 */ 57092 57093 57094function newTrustedFunctionForDev(...args) { 57095 if (typeof ngDevMode === 'undefined') { 57096 throw new Error('newTrustedFunctionForDev should never be called in production'); 57097 } 57098 57099 if (!_global.trustedTypes) { 57100 // In environments that don't support Trusted Types, fall back to the most 57101 // straightforward implementation: 57102 return new Function(...args); 57103 } // Chrome currently does not support passing TrustedScript to the Function 57104 // constructor. The following implements the workaround proposed on the page 57105 // below, where the Chromium bug is also referenced: 57106 // https://github.com/w3c/webappsec-trusted-types/wiki/Trusted-Types-for-function-constructor 57107 57108 57109 const fnArgs = args.slice(0, -1).join(','); 57110 const fnBody = args[args.length - 1]; 57111 const body = `(function anonymous(${fnArgs} 57112) { ${fnBody} 57113})`; // Using eval directly confuses the compiler and prevents this module from 57114 // being stripped out of JS binaries even if not used. The global['eval'] 57115 // indirection fixes that. 57116 57117 const fn = _global['eval'](trustedScriptFromString(body)); 57118 57119 if (fn.bind === undefined) { 57120 // Workaround for a browser bug that only exists in Chrome 83, where passing 57121 // a TrustedScript to eval just returns the TrustedScript back without 57122 // evaluating it. In that case, fall back to the most straightforward 57123 // implementation: 57124 return new Function(...args); 57125 } // To completely mimic the behavior of calling "new Function", two more 57126 // things need to happen: 57127 // 1. Stringifying the resulting function should return its source code 57128 57129 57130 fn.toString = () => body; // 2. When calling the resulting function, `this` should refer to `global` 57131 57132 57133 return fn.bind(_global); // When Trusted Types support in Function constructors is widely available, 57134 // the implementation of this function can be simplified to: 57135 // return new Function(...args.map(a => trustedScriptFromString(a))); 57136} 57137/** 57138 * @license 57139 * Copyright Google LLC All Rights Reserved. 57140 * 57141 * Use of this source code is governed by an MIT-style license that can be 57142 * found in the LICENSE file at https://angular.io/license 57143 */ 57144 57145/** 57146 * The Trusted Types policy, or null if Trusted Types are not 57147 * enabled/supported, or undefined if the policy has not been created yet. 57148 */ 57149 57150 57151let policy; 57152/** 57153 * Returns the Trusted Types policy, or null if Trusted Types are not 57154 * enabled/supported. The first call to this function will create the policy. 57155 */ 57156 57157function getPolicy() { 57158 if (policy === undefined) { 57159 policy = null; 57160 57161 if (_global.trustedTypes) {
57162 try { 57163 policy = _global.trustedTypes.createPolicy('angular#unsafe-bypass', { 57164 createHTML: s => s, 57165 createScript: s => s, 57166 createScriptURL: s => s 57167 }); 57168 } catch {// trustedTypes.createPolicy throws if called with a name that is 57169 // already registered, even in report-only mode. Until the API changes, 57170 // catch the error not to break the applications functionally. In such 57171 // cases, the code will fall back to using strings. 57172 } 57173 } 57174 } 57175 57176 return policy; 57177} 57178/** 57179 * Unsafely promote a string to a TrustedHTML, falling back to strings when 57180 * Trusted Types are not available. 57181 * @security This is a security-sensitive function; any use of this function 57182 * must go through security review. In particular, it must be assured that it 57183 * is only passed strings that come directly from custom sanitizers or the 57184 * bypassSecurityTrust* functions. 57185 */ 57186 57187 57188function trustedHTMLFromStringBypass(html) { 57189 return getPolicy()?.createHTML(html) || html; 57190} 57191/** 57192 * Unsafely promote a string to a TrustedScript, falling back to strings when 57193 * Trusted Types are not available. 57194 * @security This is a security-sensitive function; any use of this function 57195 * must go through security review. In particular, it must be assured that it 57196 * is only passed strings that come directly from custom sanitizers or the 57197 * bypassSecurityTrust* functions. 57198 */ 57199 57200 57201function trustedScriptFromStringBypass(script) { 57202 return getPolicy()?.createScript(script) || script; 57203} 57204/** 57205 * Unsafely promote a string to a TrustedScriptURL, falling back to strings 57206 * when Trusted Types are not available. 57207 * @security This is a security-sensitive function; any use of this function 57208 * must go through security review. In particular, it must be assured that it 57209 * is only passed strings that come directly from custom sanitizers or the 57210 * bypassSecurityTrust* functions. 57211 */ 57212 57213 57214function trustedScriptURLFromStringBypass(url) { 57215 return getPolicy()?.createScriptURL(url) || url; 57216} 57217/** 57218 * @license 57219 * Copyright Google LLC All Rights Reserved. 57220 * 57221 * Use of this source code is governed by an MIT-style license that can be 57222 * found in the LICENSE file at https://angular.io/license 57223 */ 57224 57225 57226class SafeValueImpl { 57227 constructor(changingThisBreaksApplicationSecurity) { 57228 this.changingThisBreaksApplicationSecurity = changingThisBreaksApplicationSecurity; 57229 } 57230 57231 toString() { 57232 return `SafeValue must use [property]=binding: ${this.changingThisBreaksApplicationSecurity}` + ` (see https://g.co/ng/security#xss)`; 57233 } 57234 57235} 57236 57237class SafeHtmlImpl extends SafeValueImpl { 57238 getTypeName() { 57239 return "HTML" 57240 /* BypassType.Html */ 57241 ; 57242 } 57243 57244} 57245 57246class SafeStyleImpl extends SafeValueImpl { 57247 getTypeName() { 57248 return "Style" 57249 /* BypassType.Style */ 57250 ; 57251 } 57252 57253} 57254 57255class SafeScriptImpl extends SafeValueImpl { 57256 getTypeName() { 57257 return "Script" 57258 /* BypassType.Script */ 57259 ; 57260 } 57261 57262} 57263 57264class SafeUrlImpl extends SafeValueImpl { 57265 getTypeName() { 57266 return "URL" 57267 /* BypassType.Url */ 57268 ; 57269 } 57270 57271} 57272 57273class SafeResourceUrlImpl extends SafeValueImpl { 57274 getTypeName() { 57275 return "ResourceURL" 57276 /* BypassType.ResourceUrl */ 57277 ; 57278 } 57279 57280} 57281 57282function unwrapSafeValue(value) { 57283 return value instanceof SafeValueImpl ? value.changingThisBreaksApplicationSecurity : value; 57284} 57285 57286function allowSanitizationBypassAndThrow(value, type) { 57287 const actualType = getSanitizationBypassType(value); 57288 57289 if (actualType != null && actualType !== type) { 57290 // Allow ResourceURLs in URL contexts, they are strictly more trusted. 57291 if (actualType === "ResourceURL" 57292 /* BypassType.ResourceUrl */ 57293 && type === "URL" 57294 /* BypassType.Url */ 57295 ) return true; 57296 throw new Error(`Required a safe ${type}, got a ${actualType} (see https://g.co/ng/security#xss)`); 57297 } 57298 57299 return actualType === type; 57300} 57301 57302function getSanitizationBypassType(value) { 57303 return value instanceof SafeValueImpl && value.getTypeName() || null; 57304} 57305/** 57306 * Mark `html` string as trusted. 57307 * 57308 * This function wraps the trusted string in `String` and brands it in a way which makes it 57309 * recognizable to {@link htmlSanitizer} to be trusted implicitly. 57310 * 57311 * @param trustedHtml `html` string which needs to be implicitly trusted. 57312 * @returns a `html` which has been branded to be implicitly trusted. 57313 */ 57314 57315 57316function bypassSanitizationTrustHtml(trustedHtml) { 57317 return new SafeHtmlImpl(trustedHtml); 57318} 57319/** 57320 * Mark `style` string as trusted. 57321 * 57322 * This function wraps the trusted string in `String` and brands it in a way which makes it 57323 * recognizable to {@link styleSanitizer} to be trusted implicitly. 57324 * 57325 * @param trustedStyle `style` string which needs to be implicitly trusted. 57326 * @returns a `style` hich has been branded to be implicitly trusted. 57327 */ 57328 57329 57330function bypassSanitizationTrustStyle(trustedStyle) { 57331 return new SafeStyleImpl(trustedStyle); 57332} 57333/** 57334 * Mark `script` string as trusted. 57335 * 57336 * This function wraps the trusted string in `String` and brands it in a way which makes it 57337 * recognizable to {@link scriptSanitizer} to be trusted implicitly. 57338 * 57339 * @param trustedScript `script` string which needs to be implicitly trusted. 57340 * @returns a `script` which has been branded to be implicitly trusted. 57341 */ 57342 57343 57344function bypassSanitizationTrustScript(trustedScript) { 57345 return new SafeScriptImpl(trustedScript); 57346} 57347/** 57348 * Mark `url` string as trusted. 57349 * 57350 * This function wraps the trusted string in `String` and brands it in a way which makes it 57351 * recognizable to {@link urlSanitizer} to be trusted implicitly. 57352 * 57353 * @param trustedUrl `url` string which needs to be implicitly trusted. 57354 * @returns a `url` which has been branded to be implicitly trusted. 57355 */ 57356 57357 57358function bypassSanitizationTrustUrl(trustedUrl) { 57359 return new SafeUrlImpl(trustedUrl); 57360} 57361/** 57362 * Mark `url` string as trusted. 57363 * 57364 * This function wraps the trusted string in `String` and brands it in a way which makes it 57365 * recognizable to {@link resourceUrlSanitizer} to be trusted implicitly. 57366 * 57367 * @param trustedResourceUrl `url` string which needs to be implicitly trusted. 57368 * @returns a `url` which has been branded to be implicitly trusted. 57369 */ 57370 57371 57372function bypassSanitizationTrustResourceUrl(trustedResourceUrl) { 57373 return new SafeResourceUrlImpl(trustedResourceUrl); 57374} 57375/** 57376 * @license 57377 * Copyright Google LLC All Rights Reserved. 57378 * 57379 * Use of this source code is governed by an MIT-style license that can be 57380 * found in the LICENSE file at https://angular.io/license 57381 */ 57382 57383/** 57384 * This helper is used to get hold of an inert tree of DOM elements containing dirty HTML 57385 * that needs sanitizing. 57386 * Depending upon browser support we use one of two strategies for doing this. 57387 * Default: DOMParser strategy 57388 * Fallback: InertDocument strategy 57389 */ 57390 57391 57392function getInertBodyHelper(defaultDoc) { 57393 const inertDocumentHelper = new InertDocumentHelper(defaultDoc); 57394 return isDOMParserAvailable() ? new DOMParserHelper(inertDocumentHelper) : inertDocumentHelper; 57395} 57396/** 57397 * Uses DOMParser to create and fill an inert body element. 57398 * This is the default strategy used in browsers that support it. 57399 */ 57400 57401 57402class DOMParserHelper { 57403 constructor(inertDocumentHelper) { 57404 this.inertDocumentHelper = inertDocumentHelper; 57405 } 57406 57407 getInertBodyElement(html) { 57408 // We add these extra elements to ensure that the rest of the content is parsed as expected 57409 // e.g. leading whitespace is maintained and tags like `<meta>` do not get hoisted to the 57410 // `<head>` tag. Note that the `<body>` tag is closed implicitly to prevent unclosed tags 57411 // in `html` from consuming the otherwise explicit `</body>` tag. 57412 html = '<body><remove></remove>' + html; 57413 57414 try { 57415 const body = new window.DOMParser().parseFromString(trustedHTMLFromString(html), 'text/html').body; 57416 57417 if (body === null) { 57418 // In some browsers (e.g. Mozilla/5.0 iPad AppleWebKit Mobile) the `body` property only 57419 // becomes available in the following tick of the JS engine. In that case we fall back to 57420 // the `inertDocumentHelper` instead. 57421 return this.inertDocumentHelper.getInertBodyElement(html); 57422 } 57423 57424 body.removeChild(body.firstChild); 57425 return body; 57426 } catch { 57427 return null; 57428 } 57429 } 57430 57431} 57432/** 57433 * Use an HTML5 `template` element, if supported, or an inert body element created via 57434 * `createHtmlDocument` to create and fill an inert DOM element. 57435 * This is the fallback strategy if the browser does not support DOMParser. 57436 */ 57437 57438 57439class InertDocumentHelper { 57440 constructor(defaultDoc) { 57441 this.defaultDoc = defaultDoc; 57442 this.inertDocument = this.defaultDoc.implementation.createHTMLDocument('sanitization-inert'); 57443 57444 if (this.inertDocument.body == null) { 57445 // usually there should be only one body element in the document, but IE doesn't have any, so 57446 // we need to create one. 57447 const inertHtml = this.inertDocument.createElement('html'); 57448 this.inertDocument.appendChild(inertHtml); 57449 const inertBodyElement = this.inertDocument.createElement('body'); 57450 inertHtml.appendChild(inertBodyElement); 57451 } 57452 } 57453 57454 getInertBodyElement(html) { 57455 // Prefer using <template> element if supported. 57456 const templateEl = this.inertDocument.createElement('template'); 57457
57458 if ('content' in templateEl) { 57459 templateEl.innerHTML = trustedHTMLFromString(html); 57460 return templateEl; 57461 } // Note that previously we used to do something like `this.inertDocument.body.innerHTML = html` 57462 // and we returned the inert `body` node. This was changed, because IE seems to treat setting 57463 // `innerHTML` on an inserted element differently, compared to one that hasn't been inserted 57464 // yet. In particular, IE appears to split some of the text into multiple text nodes rather 57465 // than keeping them in a single one which ends up messing with Ivy's i18n parsing further 57466 // down the line. This has been worked around by creating a new inert `body` and using it as 57467 // the root node in which we insert the HTML. 57468 57469 57470 const inertBody = this.inertDocument.createElement('body'); 57471 inertBody.innerHTML = trustedHTMLFromString(html); // Support: IE 11 only 57472 // strip custom-namespaced attributes on IE<=11 57473 57474 if (this.defaultDoc.documentMode) { 57475 this.stripCustomNsAttrs(inertBody); 57476 } 57477 57478 return inertBody; 57479 } 57480 /** 57481 * When IE11 comes across an unknown namespaced attribute e.g. 'xlink:foo' it adds 'xmlns:ns1' 57482 * attribute to declare ns1 namespace and prefixes the attribute with 'ns1' (e.g. 57483 * 'ns1:xlink:foo'). 57484 * 57485 * This is undesirable since we don't want to allow any of these custom attributes. This method 57486 * strips them all. 57487 */ 57488 57489 57490 stripCustomNsAttrs(el) { 57491 const elAttrs = el.attributes; // loop backwards so that we can support removals. 57492 57493 for (let i = elAttrs.length - 1; 0 < i; i--) { 57494 const attrib = elAttrs.item(i); 57495 const attrName = attrib.name; 57496 57497 if (attrName === 'xmlns:ns1' || attrName.indexOf('ns1:') === 0) { 57498 el.removeAttribute(attrName); 57499 } 57500 } 57501 57502 let childNode = el.firstChild; 57503 57504 while (childNode) { 57505 if (childNode.nodeType === Node.ELEMENT_NODE) this.stripCustomNsAttrs(childNode); 57506 childNode = childNode.nextSibling; 57507 } 57508 } 57509 57510} 57511/** 57512 * We need to determine whether the DOMParser exists in the global context and 57513 * supports parsing HTML; HTML parsing support is not as wide as other formats, see 57514 * https://developer.mozilla.org/en-US/docs/Web/API/DOMParser#Browser_compatibility. 57515 * 57516 * @suppress {uselessCode} 57517 */ 57518 57519 57520function isDOMParserAvailable() { 57521 try { 57522 return !!new window.DOMParser().parseFromString(trustedHTMLFromString(''), 'text/html'); 57523 } catch { 57524 return false; 57525 } 57526} 57527/** 57528 * @license 57529 * Copyright Google LLC All Rights Reserved. 57530 * 57531 * Use of this source code is governed by an MIT-style license that can be 57532 * found in the LICENSE file at https://angular.io/license 57533 */ 57534 57535/** 57536 * A pattern that recognizes a commonly useful subset of URLs that are safe. 57537 * 57538 * This regular expression matches a subset of URLs that will not cause script 57539 * execution if used in URL context within a HTML document. Specifically, this 57540 * regular expression matches if (comment from here on and regex copied from 57541 * Soy's EscapingConventions): 57542 * (1) Either an allowed protocol (http, https, mailto or ftp). 57543 * (2) or no protocol. A protocol must be followed by a colon. The below 57544 * allows that by allowing colons only after one of the characters [/?#]. 57545 * A colon after a hash (#) must be in the fragment. 57546 * Otherwise, a colon after a (?) must be in a query. 57547 * Otherwise, a colon after a single solidus (/) must be in a path. 57548 * Otherwise, a colon after a double solidus (//) must be in the authority 57549 * (before port). 57550 * 57551 * The pattern disallows &, used in HTML entity declarations before 57552 * one of the characters in [/?#]. This disallows HTML entities used in the 57553 * protocol name, which should never happen, e.g. "http" for "http". 57554 * It also disallows HTML entities in the first path part of a relative path, 57555 * e.g. "foo<bar/baz". Our existing escaping functions should not produce 57556 * that. More importantly, it disallows masking of a colon, 57557 * e.g. "javascript:...". 57558 * 57559 * This regular expression was taken from the Closure sanitization library. 57560 */ 57561 57562 57563const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|data|ftp|tel|file|sms):|[^&:/?#]*(?:[/?#]|$))/gi; 57564 57565function _sanitizeUrl(url) { 57566 url = String(url); 57567 if (url.match(SAFE_URL_PATTERN)) return url; 57568 57569 if (typeof ngDevMode === 'undefined' || ngDevMode) { 57570 console.warn(`WARNING: sanitizing unsafe URL value ${url} (see https://g.co/ng/security#xss)`); 57571 } 57572 57573 return 'unsafe:' + url; 57574} 57575/** 57576 * @license 57577 * Copyright Google LLC All Rights Reserved. 57578 * 57579 * Use of this source code is governed by an MIT-style license that can be 57580 * found in the LICENSE file at https://angular.io/license 57581 */ 57582 57583 57584function tagSet(tags) { 57585 const res = {}; 57586 57587 for (const t of tags.split(',')) res[t] = true; 57588 57589 return res; 57590} 57591 57592function merge(...sets) { 57593 const res = {}; 57594
57595 for (const s of sets) { 57596 for (const v in s) { 57597 if (s.hasOwnProperty(v)) res[v] = true; 57598 } 57599 } 57600 57601 return res; 57602} // Good source of info about elements and attributes 57603// https://html.spec.whatwg.org/#semantics 57604// https://simon.html5.org/html-elements 57605// Safe Void Elements - HTML5 57606// https://html.spec.whatwg.org/#void-elements 57607 57608 57609const VOID_ELEMENTS = tagSet('area,br,col,hr,img,wbr'); // Elements that you can, intentionally, leave open (and which close themselves) 57610// https://html.spec.whatwg.org/#optional-tags 57611 57612const OPTIONAL_END_TAG_BLOCK_ELEMENTS = tagSet('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr'); 57613const OPTIONAL_END_TAG_INLINE_ELEMENTS = tagSet('rp,rt'); 57614const OPTIONAL_END_TAG_ELEMENTS = merge(OPTIONAL_END_TAG_INLINE_ELEMENTS, OPTIONAL_END_TAG_BLOCK_ELEMENTS); // Safe Block Elements - HTML5 57615 57616const BLOCK_ELEMENTS = merge(OPTIONAL_END_TAG_BLOCK_ELEMENTS, tagSet('address,article,' + 'aside,blockquote,caption,center,del,details,dialog,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,' + 'h6,header,hgroup,hr,ins,main,map,menu,nav,ol,pre,section,summary,table,ul')); // Inline Elements - HTML5 57617 57618const INLINE_ELEMENTS = merge(OPTIONAL_END_TAG_INLINE_ELEMENTS, tagSet('a,abbr,acronym,audio,b,' + 'bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,picture,q,ruby,rp,rt,s,' + 'samp,small,source,span,strike,strong,sub,sup,time,track,tt,u,var,video')); 57619const VALID_ELEMENTS = merge(VOID_ELEMENTS, BLOCK_ELEMENTS, INLINE_ELEMENTS, OPTIONAL_END_TAG_ELEMENTS); // Attributes that have href and hence need to be sanitized 57620 57621const URI_ATTRS = tagSet('background,cite,href,itemtype,longdesc,poster,src,xlink:href'); 57622const HTML_ATTRS = tagSet('abbr,accesskey,align,alt,autoplay,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,' + 'compact,controls,coords,datetime,default,dir,download,face,headers,height,hidden,hreflang,hspace,' + 'ismap,itemscope,itemprop,kind,label,lang,language,loop,media,muted,nohref,nowrap,open,preload,rel,rev,role,rows,rowspan,rules,' + 'scope,scrolling,shape,size,sizes,span,srclang,srcset,start,summary,tabindex,target,title,translate,type,usemap,' + 'valign,value,vspace,width'); // Accessibility attributes as per WAI-ARIA 1.1 (W3C Working Draft 14 December 2018) 57623 57624const ARIA_ATTRS = tagSet('aria-activedescendant,aria-atomic,aria-autocomplete,aria-busy,aria-checked,aria-colcount,aria-colindex,' + 'aria-colspan,aria-controls,aria-current,aria-describedby,aria-details,aria-disabled,aria-dropeffect,' + 'aria-errormessage,aria-expanded,aria-flowto,aria-grabbed,aria-haspopup,aria-hidden,aria-invalid,' + 'aria-keyshortcuts,aria-label,aria-labelledby,aria-level,aria-live,aria-modal,aria-multiline,' + 'aria-multiselectable,aria-orientation,aria-owns,aria-placeholder,aria-posinset,aria-pressed,aria-readonly,' + 'aria-relevant,aria-required,aria-roledescription,aria-rowcount,aria-rowindex,aria-rowspan,aria-selected,' + 'aria-setsize,aria-sort,aria-valuemax,aria-valuemin,aria-valuenow,aria-valuetext'); // NB: This currently consciously doesn't support SVG. SVG sanitization has had several security 57625// issues in the past, so it seems safer to leave it out if possible. If support for binding SVG via 57626// innerHTML is required, SVG attributes should be added here. 57627// NB: Sanitization does not allow <form> elements or other active elements (<button> etc). Those 57628// can be sanitized, but they increase security surface area without a legitimate use case, so they 57629// are left out here. 57630 57631const VALID_ATTRS = merge(URI_ATTRS, HTML_ATTRS, ARIA_ATTRS); // Elements whose content should not be traversed/preserved, if the elements themselves are invalid. 57632// 57633// Typically, `<invalid>Some content</invalid>` would traverse (and in this case preserve) 57634// `Some content`, but strip `invalid-element` opening/closing tags. For some elements, though, we 57635// don't want to preserve the content, if the elements themselves are going to be removed. 57636 57637const SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS = tagSet('script,style,template'); 57638/**
57639 * SanitizingHtmlSerializer serializes a DOM fragment, stripping out any unsafe elements and unsafe 57640 * attributes. 57641 */ 57642 57643class SanitizingHtmlSerializer { 57644 constructor() { 57645 // Explicitly track if something was stripped, to avoid accidentally warning of sanitization just 57646 // because characters were re-encoded. 57647 this.sanitizedSomething = false; 57648 this.buf = []; 57649 } 57650 57651 sanitizeChildren(el) { 57652 // This cannot use a TreeWalker, as it has to run on Angular's various DOM adapters. 57653 // However this code never accesses properties off of `document` before deleting its contents 57654 // again, so it shouldn't be vulnerable to DOM clobbering. 57655 let current = el.firstChild; 57656 let traverseContent = true; 57657 57658 while (current) { 57659 if (current.nodeType === Node.ELEMENT_NODE) { 57660 traverseContent = this.startElement(current); 57661 } else if (current.nodeType === Node.TEXT_NODE) { 57662 this.chars(current.nodeValue); 57663 } else { 57664 // Strip non-element, non-text nodes. 57665 this.sanitizedSomething = true; 57666 } 57667 57668 if (traverseContent && current.firstChild) { 57669 current = current.firstChild; 57670 continue; 57671 } 57672 57673 while (current) { 57674 // Leaving the element. Walk up and to the right, closing tags as we go. 57675 if (current.nodeType === Node.ELEMENT_NODE) { 57676 this.endElement(current); 57677 } 57678 57679 let next = this.checkClobberedElement(current, current.nextSibling); 57680 57681 if (next) { 57682 current = next; 57683 break; 57684 } 57685 57686 current = this.checkClobberedElement(current, current.parentNode); 57687 } 57688 } 57689 57690 return this.buf.join(''); 57691 } 57692 /** 57693 * Sanitizes an opening element tag (if valid) and returns whether the element's contents should 57694 * be traversed. Element content must always be traversed (even if the element itself is not 57695 * valid/safe), unless the element is one of `SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS`. 57696 * 57697 * @param element The element to sanitize. 57698 * @return True if the element's contents should be traversed. 57699 */ 57700 57701 57702 startElement(element) { 57703 const tagName = element.nodeName.toLowerCase(); 57704 57705 if (!VALID_ELEMENTS.hasOwnProperty(tagName)) { 57706 this.sanitizedSomething = true; 57707 return !SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS.hasOwnProperty(tagName); 57708 } 57709 57710 this.buf.push('<'); 57711 this.buf.push(tagName); 57712 const elAttrs = element.attributes; 57713 57714 for (let i = 0; i < elAttrs.length; i++) { 57715 const elAttr = elAttrs.item(i); 57716 const attrName = elAttr.name; 57717 const lower = attrName.toLowerCase(); 57718 57719 if (!VALID_ATTRS.hasOwnProperty(lower)) { 57720 this.sanitizedSomething = true; 57721 continue; 57722 } 57723 57724 let value = elAttr.value; // TODO(martinprobst): Special case image URIs for data:image/... 57725 57726 if (URI_ATTRS[lower]) value = _sanitizeUrl(value); 57727 this.buf.push(' ', attrName, '="', encodeEntities(value), '"'); 57728 } 57729 57730 this.buf.push('>'); 57731 return true; 57732 } 57733 57734 endElement(current) { 57735 const tagName = current.nodeName.toLowerCase(); 57736 57737 if (VALID_ELEMENTS.hasOwnProperty(tagName) && !VOID_ELEMENTS.hasOwnProperty(tagName)) { 57738 this.buf.push('</'); 57739 this.buf.push(tagName); 57740 this.buf.push('>'); 57741 } 57742 } 57743 57744 chars(chars) { 57745 this.buf.push(encodeEntities(chars)); 57746 } 57747 57748 checkClobberedElement(node, nextNode) { 57749 if (nextNode && (node.compareDocumentPosition(nextNode) & Node.DOCUMENT_POSITION_CONTAINED_BY) === Node.DOCUMENT_POSITION_CONTAINED_BY) { 57750 throw new Error(`Failed to sanitize html because the element is clobbered: ${node.outerHTML}`); 57751 } 57752 57753 return nextNode; 57754 } 57755 57756} // Regular Expressions for parsing tags and attributes 57757 57758 57759const SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; // ! to ~ is the ASCII range. 57760 57761const NON_ALPHANUMERIC_REGEXP = /([^\#-~ |!])/g; 57762/** 57763 * Escapes all potentially dangerous characters, so that the 57764 * resulting string can be safely inserted into attribute or 57765 * element text. 57766 * @param value 57767 */ 57768 57769function encodeEntities(value) { 57770 return value.replace(/&/g, '&').replace(SURROGATE_PAIR_REGEXP, function (match) {
vendor: 13,587 bytes, lines 57771-58170
57771 const hi = match.charCodeAt(0); 57772 const low = match.charCodeAt(1); 57773 return '&#' + ((hi - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000) + ';'; 57774 }).replace(NON_ALPHANUMERIC_REGEXP, function (match) { 57775 return '&#' + match.charCodeAt(0) + ';'; 57776 }).replace(/</g, '<').replace(/>/g, '>'); 57777} 57778 57779let inertBodyHelper; 57780/** 57781 * Sanitizes the given unsafe, untrusted HTML fragment, and returns HTML text that is safe to add to 57782 * the DOM in a browser environment. 57783 */ 57784 57785function _sanitizeHtml(defaultDoc, unsafeHtmlInput) { 57786 let inertBodyElement = null; 57787 57788 try { 57789 inertBodyHelper = inertBodyHelper || getInertBodyHelper(defaultDoc); // Make sure unsafeHtml is actually a string (TypeScript types are not enforced at runtime). 57790 57791 let unsafeHtml = unsafeHtmlInput ? String(unsafeHtmlInput) : ''; 57792 inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml); // mXSS protection. Repeatedly parse the document to make sure it stabilizes, so that a browser 57793 // trying to auto-correct incorrect HTML cannot cause formerly inert HTML to become dangerous. 57794 57795 let mXSSAttempts = 5; 57796 let parsedHtml = unsafeHtml; 57797 57798 do { 57799 if (mXSSAttempts === 0) { 57800 throw new Error('Failed to sanitize html because the input is unstable'); 57801 } 57802 57803 mXSSAttempts--; 57804 unsafeHtml = parsedHtml; 57805 parsedHtml = inertBodyElement.innerHTML; 57806 inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml); 57807 } while (unsafeHtml !== parsedHtml); 57808 57809 const sanitizer = new SanitizingHtmlSerializer(); 57810 const safeHtml = sanitizer.sanitizeChildren(getTemplateContent(inertBodyElement) || inertBodyElement); 57811 57812 if ((typeof ngDevMode === 'undefined' || ngDevMode) && sanitizer.sanitizedSomething) { 57813 console.warn('WARNING: sanitizing HTML stripped some content, see https://g.co/ng/security#xss'); 57814 } 57815 57816 return trustedHTMLFromString(safeHtml); 57817 } finally { 57818 // In case anything goes wrong, clear out inertElement to reset the entire DOM structure. 57819 if (inertBodyElement) { 57820 const parent = getTemplateContent(inertBodyElement) || inertBodyElement; 57821 57822 while (parent.firstChild) { 57823 parent.removeChild(parent.firstChild); 57824 } 57825 } 57826 } 57827} 57828 57829function getTemplateContent(el) { 57830 return 'content' in el 57831 /** Microsoft/TypeScript#21517 */ 57832 && isTemplateElement(el) ? el.content : null; 57833} 57834 57835function isTemplateElement(el) { 57836 return el.nodeType === Node.ELEMENT_NODE && el.nodeName === 'TEMPLATE'; 57837} 57838/** 57839 * @license 57840 * Copyright Google LLC All Rights Reserved. 57841 * 57842 * Use of this source code is governed by an MIT-style license that can be 57843 * found in the LICENSE file at https://angular.io/license 57844 */ 57845 57846/** 57847 * A SecurityContext marks a location that has dangerous security implications, e.g. a DOM property 57848 * like `innerHTML` that could cause Cross Site Scripting (XSS) security bugs when improperly 57849 * handled. 57850 * 57851 * See DomSanitizer for more details on security in Angular applications. 57852 * 57853 * @publicApi 57854 */ 57855 57856 57857var SecurityContext; 57858 57859(function (SecurityContext) { 57860 SecurityContext[SecurityContext["NONE"] = 0] = "NONE"; 57861 SecurityContext[SecurityContext["HTML"] = 1] = "HTML"; 57862 SecurityContext[SecurityContext["STYLE"] = 2] = "STYLE"; 57863 SecurityContext[SecurityContext["SCRIPT"] = 3] = "SCRIPT"; 57864 SecurityContext[SecurityContext["URL"] = 4] = "URL"; 57865 SecurityContext[SecurityContext["RESOURCE_URL"] = 5] = "RESOURCE_URL"; 57866})(SecurityContext || (SecurityContext = {})); 57867/** 57868 * @license 57869 * Copyright Google LLC All Rights Reserved. 57870 * 57871 * Use of this source code is governed by an MIT-style license that can be 57872 * found in the LICENSE file at https://angular.io/license 57873 */ 57874 57875/** 57876 * An `html` sanitizer which converts untrusted `html` **string** into trusted string by removing 57877 * dangerous content. 57878 * 57879 * This method parses the `html` and locates potentially dangerous content (such as urls and 57880 * javascript) and removes it. 57881 * 57882 * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustHtml}. 57883 * 57884 * @param unsafeHtml untrusted `html`, typically from the user. 57885 * @returns `html` string which is safe to display to user, because all of the dangerous javascript 57886 * and urls have been removed. 57887 * 57888 * @codeGenApi 57889 */ 57890 57891 57892function ɵɵsanitizeHtml(unsafeHtml) { 57893 const sanitizer = getSanitizer(); 57894 57895 if (sanitizer) { 57896 return trustedHTMLFromStringBypass(sanitizer.sanitize(SecurityContext.HTML, unsafeHtml) || ''); 57897 } 57898 57899 if (allowSanitizationBypassAndThrow(unsafeHtml, "HTML" 57900 /* BypassType.Html */ 57901 )) { 57902 return trustedHTMLFromStringBypass(unwrapSafeValue(unsafeHtml)); 57903 } 57904 57905 return _sanitizeHtml(getDocument(), renderStringify(unsafeHtml)); 57906} 57907/** 57908 * A `style` sanitizer which converts untrusted `style` **string** into trusted string by removing 57909 * dangerous content. 57910 * 57911 * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustStyle}. 57912 * 57913 * @param unsafeStyle untrusted `style`, typically from the user. 57914 * @returns `style` string which is safe to bind to the `style` properties. 57915 * 57916 * @codeGenApi 57917 */ 57918 57919 57920function ɵɵsanitizeStyle(unsafeStyle) { 57921 const sanitizer = getSanitizer(); 57922 57923 if (sanitizer) { 57924 return sanitizer.sanitize(SecurityContext.STYLE, unsafeStyle) || ''; 57925 } 57926 57927 if (allowSanitizationBypassAndThrow(unsafeStyle, "Style" 57928 /* BypassType.Style */ 57929 )) { 57930 return unwrapSafeValue(unsafeStyle); 57931 } 57932 57933 return renderStringify(unsafeStyle); 57934} 57935/** 57936 * A `url` sanitizer which converts untrusted `url` **string** into trusted string by removing 57937 * dangerous 57938 * content. 57939 * 57940 * This method parses the `url` and locates potentially dangerous content (such as javascript) and 57941 * removes it. 57942 * 57943 * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustUrl}. 57944 * 57945 * @param unsafeUrl untrusted `url`, typically from the user. 57946 * @returns `url` string which is safe to bind to the `src` properties such as `<img src>`, because 57947 * all of the dangerous javascript has been removed. 57948 * 57949 * @codeGenApi 57950 */ 57951 57952 57953function ɵɵsanitizeUrl(unsafeUrl) { 57954 const sanitizer = getSanitizer(); 57955 57956 if (sanitizer) { 57957 return sanitizer.sanitize(SecurityContext.URL, unsafeUrl) || ''; 57958 } 57959 57960 if (allowSanitizationBypassAndThrow(unsafeUrl, "URL" 57961 /* BypassType.Url */ 57962 )) { 57963 return unwrapSafeValue(unsafeUrl); 57964 } 57965 57966 return _sanitizeUrl(renderStringify(unsafeUrl)); 57967} 57968/** 57969 * A `url` sanitizer which only lets trusted `url`s through. 57970 * 57971 * This passes only `url`s marked trusted by calling {@link bypassSanitizationTrustResourceUrl}. 57972 * 57973 * @param unsafeResourceUrl untrusted `url`, typically from the user. 57974 * @returns `url` string which is safe to bind to the `src` properties such as `<img src>`, because 57975 * only trusted `url`s have been allowed to pass. 57976 * 57977 * @codeGenApi 57978 */ 57979 57980 57981function ɵɵsanitizeResourceUrl(unsafeResourceUrl) { 57982 const sanitizer = getSanitizer(); 57983 57984 if (sanitizer) { 57985 return trustedScriptURLFromStringBypass(sanitizer.sanitize(SecurityContext.RESOURCE_URL, unsafeResourceUrl) || ''); 57986 } 57987 57988 if (allowSanitizationBypassAndThrow(unsafeResourceUrl, "ResourceURL" 57989 /* BypassType.ResourceUrl */ 57990 )) { 57991 return trustedScriptURLFromStringBypass(unwrapSafeValue(unsafeResourceUrl)); 57992 } 57993 57994 throw new RuntimeError(904 57995 /* RuntimeErrorCode.UNSAFE_VALUE_IN_RESOURCE_URL */ 57996 , ngDevMode && 'unsafe value used in a resource URL context (see https://g.co/ng/security#xss)'); 57997} 57998/** 57999 * A `script` sanitizer which only lets trusted javascript through. 58000 * 58001 * This passes only `script`s marked trusted by calling {@link 58002 * bypassSanitizationTrustScript}. 58003 * 58004 * @param unsafeScript untrusted `script`, typically from the user. 58005 * @returns `url` string which is safe to bind to the `<script>` element such as `<img src>`, 58006 * because only trusted `scripts` have been allowed to pass. 58007 * 58008 * @codeGenApi 58009 */ 58010 58011 58012function ɵɵsanitizeScript(unsafeScript) { 58013 const sanitizer = getSanitizer(); 58014 58015 if (sanitizer) { 58016 return trustedScriptFromStringBypass(sanitizer.sanitize(SecurityContext.SCRIPT, unsafeScript) || ''); 58017 } 58018 58019 if (allowSanitizationBypassAndThrow(unsafeScript, "Script" 58020 /* BypassType.Script */ 58021 )) { 58022 return trustedScriptFromStringBypass(unwrapSafeValue(unsafeScript)); 58023 } 58024 58025 throw new RuntimeError(905 58026 /* RuntimeErrorCode.UNSAFE_VALUE_IN_SCRIPT */ 58027 , ngDevMode && 'unsafe value used in a script context'); 58028} 58029/** 58030 * A template tag function for promoting the associated constant literal to a 58031 * TrustedHTML. Interpolation is explicitly not allowed. 58032 * 58033 * @param html constant template literal containing trusted HTML. 58034 * @returns TrustedHTML wrapping `html`. 58035 * 58036 * @security This is a security-sensitive function and should only be used to 58037 * convert constant values of attributes and properties found in 58038 * application-provided Angular templates to TrustedHTML. 58039 * 58040 * @codeGenApi 58041 */ 58042 58043 58044function ɵɵtrustConstantHtml(html) { 58045 // The following runtime check ensures that the function was called as a 58046 // template tag (e.g. ɵɵtrustConstantHtml`content`), without any interpolation 58047 // (e.g. not ɵɵtrustConstantHtml`content ${variable}`). A TemplateStringsArray 58048 // is an array with a `raw` property that is also an array. The associated 58049 // template literal has no interpolation if and only if the length of the 58050 // TemplateStringsArray is 1. 58051 if (ngDevMode && (!Array.isArray(html) || !Array.isArray(html.raw) || html.length !== 1)) { 58052 throw new Error(`Unexpected interpolation in trusted HTML constant: ${html.join('?')}`); 58053 } 58054 58055 return trustedHTMLFromString(html[0]); 58056} 58057/** 58058 * A template tag function for promoting the associated constant literal to a 58059 * TrustedScriptURL. Interpolation is explicitly not allowed. 58060 * 58061 * @param url constant template literal containing a trusted script URL. 58062 * @returns TrustedScriptURL wrapping `url`. 58063 * 58064 * @security This is a security-sensitive function and should only be used to 58065 * convert constant values of attributes and properties found in 58066 * application-provided Angular templates to TrustedScriptURL. 58067 * 58068 * @codeGenApi 58069 */ 58070 58071 58072function ɵɵtrustConstantResourceUrl(url) { 58073 // The following runtime check ensures that the function was called as a 58074 // template tag (e.g. ɵɵtrustConstantResourceUrl`content`), without any 58075 // interpolation (e.g. not ɵɵtrustConstantResourceUrl`content ${variable}`). A 58076 // TemplateStringsArray is an array with a `raw` property that is also an 58077 // array. The associated template literal has no interpolation if and only if 58078 // the length of the TemplateStringsArray is 1. 58079 if (ngDevMode && (!Array.isArray(url) || !Array.isArray(url.raw) || url.length !== 1)) { 58080 throw new Error(`Unexpected interpolation in trusted URL constant: ${url.join('?')}`); 58081 } 58082 58083 return trustedScriptURLFromString(url[0]); 58084} 58085/** 58086 * Detects which sanitizer to use for URL property, based on tag name and prop name. 58087 * 58088 * The rules are based on the RESOURCE_URL context config from 58089 * `packages/compiler/src/schema/dom_security_schema.ts`. 58090 * If tag and prop names don't match Resource URL schema, use URL sanitizer. 58091 */ 58092 58093 58094function getUrlSanitizer(tag, prop) { 58095 if (prop === 'src' && (tag === 'embed' || tag === 'frame' || tag === 'iframe' || tag === 'media' || tag === 'script') || prop === 'href' && (tag === 'base' || tag === 'link')) { 58096 return ɵɵsanitizeResourceUrl; 58097 } 58098 58099 return ɵɵsanitizeUrl; 58100} 58101/** 58102 * Sanitizes URL, selecting sanitizer function based on tag and property names. 58103 * 58104 * This function is used in case we can't define security context at compile time, when only prop 58105 * name is available. This happens when we generate host bindings for Directives/Components. The 58106 * host element is unknown at compile time, so we defer calculation of specific sanitizer to 58107 * runtime. 58108 * 58109 * @param unsafeUrl untrusted `url`, typically from the user. 58110 * @param tag target element tag name. 58111 * @param prop name of the property that contains the value. 58112 * @returns `url` string which is safe to bind. 58113 * 58114 * @codeGenApi 58115 */ 58116 58117 58118function ɵɵsanitizeUrlOrResourceUrl(unsafeUrl, tag, prop) { 58119 return getUrlSanitizer(tag, prop)(unsafeUrl); 58120} 58121 58122function validateAgainstEventProperties(name) { 58123 if (name.toLowerCase().startsWith('on')) { 58124 const errorMessage = `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.`; 58125 throw new RuntimeError(306 58126 /* RuntimeErrorCode.INVALID_EVENT_BINDING */ 58127 , errorMessage); 58128 } 58129} 58130 58131function validateAgainstEventAttributes(name) { 58132 if (name.toLowerCase().startsWith('on')) { 58133 const errorMessage = `Binding to event attribute '${name}' is disallowed for security reasons, ` + `please use (${name.slice(2)})=...`; 58134 throw new RuntimeError(306 58135 /* RuntimeErrorCode.INVALID_EVENT_BINDING */ 58136 , errorMessage); 58137 } 58138} 58139 58140function getSanitizer() { 58141 const lView = getLView(); 58142 return lView && lView[SANITIZER]; 58143} 58144/** 58145 * @license 58146 * Copyright Google LLC All Rights Reserved. 58147 * 58148 * Use of this source code is governed by an MIT-style license that can be 58149 * found in the LICENSE file at https://angular.io/license 58150 */ 58151 58152/** 58153 * A multi-provider token for initialization functions that will run upon construction of an 58154 * environment injector. 58155 * 58156 * @publicApi 58157 */ 58158 58159 58160const ENVIRONMENT_INITIALIZER = new InjectionToken('ENVIRONMENT_INITIALIZER'); 58161/** 58162 * @license 58163 * Copyright Google LLC All Rights Reserved. 58164 * 58165 * Use of this source code is governed by an MIT-style license that can be 58166 * found in the LICENSE file at https://angular.io/license 58167 */ 58168 58169/** 58170 * An InjectionToken that gets the current `Injector` for `createInjector()`
58170-style injectors. 58171 * 58172 * Requesting this token instead of `Injector` allows `StaticInjector` to be tree-shaken from a 58173 * project. 58174 * 58175 * @publicApi 58176 */ 58177 58178const INJECTOR = new InjectionToken('INJECTOR', // Disable tslint because this is const enum which gets inlined not top level prop access. 58179// tslint:disable-next-line: no-toplevel-property-access 58180-1 58181/* InjectorMarkers.Injector */ 58182); 58183/** 58184 * @license 58185 * Copyright Google LLC All Rights Reserved. 58186 * 58187 * Use of this source code is governed by an MIT-style license that can be 58188 * found in the LICENSE file at https://angular.io/license 58189 */ 58190 58191const INJECTOR_DEF_TYPES = new InjectionToken('INJECTOR_DEF_TYPES'); 58192/** 58193 * @license 58194 * Copyright Google LLC All Rights Reserved. 58195 * 58196 * Use of this source code is governed by an MIT-style license that can be 58197 * found in the LICENSE file at https://angular.io/license 58198 */ 58199 58200class NullInjector { 58201 get(token, notFoundValue = THROW_IF_NOT_FOUND) { 58202 if (notFoundValue === THROW_IF_NOT_FOUND) { 58203 const error = new Error(`NullInjectorError: No provider for ${stringify(token)}!`); 58204 error.name = 'NullInjectorError'; 58205 throw error; 58206 } 58207 58208 return notFoundValue; 58209 } 58210 58211} 58212/** 58213 * @license 58214 * Copyright Google LLC All Rights Reserved. 58215 * 58216 * Use of this source code is governed by an MIT-style license that can be 58217 * found in the LICENSE file at https://angular.io/license 58218 */ 58219 58220/** 58221 * @license 58222 * Copyright Google LLC All Rights Reserved. 58223 * 58224 * Use of this source code is governed by an MIT-style license that can be 58225 * found in the LICENSE file at https://angular.io/license 58226 */ 58227 58228/** 58229 * Collects providers from all NgModules and standalone components, including transitively imported 58230 * ones. 58231 * 58232 * Providers extracted via `importProvidersFrom` are only usable in an application injector or 58233 * another environment injector (such as a route injector). They should not be used in component 58234 * providers. 58235 * 58236 * More information about standalone components can be found in [this 58237 * guide](guide/standalone-components). 58238 * 58239 * @usageNotes 58240 * The results of the `importProvidersFrom` call can be used in the `bootstrapApplication` call: 58241 * 58242 * ```typescript 58243 * await bootstrapApplication(RootComponent, { 58244 * providers: [ 58245 * importProvidersFrom(NgModuleOne, NgModuleTwo) 58246 * ] 58247 * }); 58248 * ``` 58249 * 58250 * You can also use the `importProvidersFrom` results in the `providers` field of a route, when a 58251 * standalone component is used: 58252 * 58253 * ```typescript 58254 * export const ROUTES: Route[] = [ 58255 * { 58256 * path: 'foo', 58257 * providers: [ 58258 * importProvidersFrom(NgModuleOne, NgModuleTwo) 58259 * ], 58260 * component: YourStandaloneComponent 58261 * } 58262 * ]; 58263 * ``` 58264 * 58265 * @returns Collected providers from the specified list of types. 58266 * @publicApi 58267 * @developerPreview 58268 */ 58269 58270 58271function importProvidersFrom(...sources) { 58272 return { 58273 ɵproviders: internalImportProvidersFrom(true, sources) 58274 }; 58275} 58276 58277function internalImportProvidersFrom(checkForStandaloneCmp, ...sources) { 58278 const providersOut = []; 58279 const dedup = new Set(); // already seen types 58280 58281 let injectorTypesWithProviders; 58282 deepForEach(sources, source => { 58283 if ((typeof ngDevMode === 'undefined' || ngDevMode) && checkForStandaloneCmp) { 58284 const cmpDef = getComponentDef(source); 58285 58286 if (cmpDef?.standalone) { 58287 throw new RuntimeError(800 58288 /* RuntimeErrorCode.IMPORT_PROVIDERS_FROM_STANDALONE */ 58289 , `Importing providers supports NgModule or ModuleWithProviders but got a standalone component "${stringifyForError(source)}"`); 58290 } 58291 } // Narrow `source` to access the internal type analogue for `ModuleWithProviders`. 58292 58293 58294 const internalSource = source; 58295 58296 if (walkProviderTree(internalSource, providersOut, [], dedup)) { 58297 injectorTypesWithProviders || (injectorTypesWithProviders = []); 58298 injectorTypesWithProviders.push(internalSource); 58299 } 58300 }); // Collect all providers from `ModuleWithProviders` types. 58301 58302 if (injectorTypesWithProviders !== undefined) { 58303 processInjectorTypesWithProviders(injectorTypesWithProviders, providersOut); 58304 } 58305 58306 return providersOut; 58307} 58308/** 58309 * Collects all providers from the list of `ModuleWithProviders` and appends them to the provided 58310 * array.
vendor: 4,938 bytes, lines 58311-58438
58311 */ 58312 58313 58314function processInjectorTypesWithProviders(typesWithProviders, providersOut) { 58315 for (let i = 0; i < typesWithProviders.length; i++) { 58316 const { 58317 ngModule, 58318 providers 58319 } = typesWithProviders[i]; 58320 deepForEach(providers, provider => { 58321 ngDevMode && validateProvider(provider, providers || EMPTY_ARRAY, ngModule); 58322 providersOut.push(provider); 58323 }); 58324 } 58325} 58326/** 58327 * The logic visits an `InjectorType`, an `InjectorTypeWithProviders`, or a standalone 58328 * `ComponentType`, and all of its transitive providers and collects providers. 58329 * 58330 * If an `InjectorTypeWithProviders` that declares providers besides the type is specified, 58331 * the function will return "true" to indicate that the providers of the type definition need 58332 * to be processed. This allows us to process providers of injector types after all imports of 58333 * an injector definition are processed. (following View Engine semantics: see FW-1349) 58334 */ 58335 58336 58337function walkProviderTree(container, providersOut, parents, dedup) { 58338 container = resolveForwardRef(container); 58339 if (!container) return false; // The actual type which had the definition. Usually `container`, but may be an unwrapped type 58340 // from `InjectorTypeWithProviders`. 58341 58342 let defType = null; 58343 let injDef = getInjectorDef(container); 58344 const cmpDef = !injDef && getComponentDef(container); 58345 58346 if (!injDef && !cmpDef) { 58347 // `container` is not an injector type or a component type. It might be: 58348 // * An `InjectorTypeWithProviders` that wraps an injector type. 58349 // * A standalone directive or pipe that got pulled in from a standalone component's 58350 // dependencies. 58351 // Try to unwrap it as an `InjectorTypeWithProviders` first. 58352 const ngModule = container.ngModule; 58353 injDef = getInjectorDef(ngModule); 58354 58355 if (injDef) { 58356 defType = ngModule; 58357 } else { 58358 // Not a component or injector type, so ignore it. 58359 return false; 58360 } 58361 } else if (cmpDef && !cmpDef.standalone) { 58362 return false; 58363 } else { 58364 defType = container; 58365 } // Check for circular dependencies. 58366 58367 58368 if (ngDevMode && parents.indexOf(defType) !== -1) { 58369 const defName = stringify(defType); 58370 const path = parents.map(stringify); 58371 throwCyclicDependencyError(defName, path); 58372 } // Check for multiple imports of the same module 58373 58374 58375 const isDuplicate = dedup.has(defType); 58376 58377 if (cmpDef) { 58378 if (isDuplicate) { 58379 // This component definition has already been processed. 58380 return false; 58381 } 58382 58383 dedup.add(defType); 58384 58385 if (cmpDef.dependencies) { 58386 const deps = typeof cmpDef.dependencies === 'function' ? cmpDef.dependencies() : cmpDef.dependencies; 58387 58388 for (const dep of deps) { 58389 walkProviderTree(dep, providersOut, parents, dedup); 58390 } 58391 } 58392 } else if (injDef) { 58393 // First, include providers from any imports. 58394 if (injDef.imports != null && !isDuplicate) { 58395 // Before processing defType's imports, add it to the set of parents. This way, if it ends 58396 // up deeply importing itself, this can be detected. 58397 ngDevMode && parents.push(defType); // Add it to the set of dedups. This way we can detect multiple imports of the same module 58398 58399 dedup.add(defType); 58400 let importTypesWithProviders; 58401 58402 try { 58403 deepForEach(injDef.imports, imported => { 58404 if (walkProviderTree(imported, providersOut, parents, dedup)) { 58405 importTypesWithProviders || (importTypesWithProviders = []); // If the processed import is an injector type with providers, we store it in the 58406 // list of import types with providers, so that we can process those afterwards. 58407 58408 importTypesWithProviders.push(imported); 58409 } 58410 }); 58411 } finally { 58412 // Remove it from the parents set when finished. 58413 ngDevMode && parents.pop(); 58414 } // Imports which are declared with providers (TypeWithProviders) need to be processed 58415 // after all imported modules are processed. This is similar to how View Engine 58416 // processes/merges module imports in the metadata resolver. See: FW-1349. 58417 58418 58419 if (importTypesWithProviders !== undefined) { 58420 processInjectorTypesWithProviders(importTypesWithProviders, providersOut); 58421 } 58422 } 58423 58424 if (!isDuplicate) { 58425 // Track the InjectorType and add a provider for it. 58426 // It's important that this is done after the def's imports. 58427 const factory = getFactoryDef(defType) || (() => new defType()); // Append extra providers to make more info available for consumers (to retrieve an injector 58428 // type), as well as internally (to calculate an injection scope correctly and eagerly 58429 // instantiate a `defType` when an injector is created). 58430 58431 58432 providersOut.push( // Provider to create `defType` using its factory. 58433 { 58434 provide: defType, 58435 useFactory: factory, 58436 deps: EMPTY_ARRAY 58437 }, // Make this `defType` available to an internal logic that calculates injector scope. 58438 {
58439 provide: INJECTOR_DEF_TYPES, 58440 useValue: defType, 58441 multi: true 58442 }, // Provider to eagerly instantiate `defType` via `ENVIRONMENT_INITIALIZER`. 58443 { 58444 provide: ENVIRONMENT_INITIALIZER, 58445 useValue: () => ɵɵinject(defType), 58446 multi: true 58447 } // 58448 ); 58449 } // Next, include providers listed on the definition itself. 58450 58451 58452 const defProviders = injDef.providers; 58453 58454 if (defProviders != null && !isDuplicate) { 58455 const injectorType = container; 58456 deepForEach(defProviders, provider => { 58457 ngDevMode && validateProvider(provider, defProviders, injectorType); 58458 providersOut.push(provider); 58459 }); 58460 } 58461 } else { 58462 // Should not happen, but just in case. 58463 return false; 58464 } 58465 58466 return defType !== container && container.providers !== undefined; 58467} 58468 58469function validateProvider(provider, providers, containerType) { 58470 if (isTypeProvider(provider) || isValueProvider(provider) || isFactoryProvider(provider) || isExistingProvider(provider)) { 58471 return; 58472 } // Here we expect the provider to be a `useClass` provider (by elimination). 58473 58474 58475 const classRef = resolveForwardRef(provider && (provider.useClass || provider.provide)); 58476 58477 if (!classRef) { 58478 throwInvalidProviderError(containerType, providers, provider); 58479 } 58480} 58481 58482const USE_VALUE$1 = getClosureSafeProperty({ 58483 provide: String, 58484 useValue: getClosureSafeProperty 58485}); 58486 58487function isValueProvider(value) { 58488 return value !== null && typeof value == 'object' && USE_VALUE$1 in value; 58489} 58490 58491function isExistingProvider(value) { 58492 return !!(value && value.useExisting); 58493} 58494 58495function isFactoryProvider(value) { 58496 return !!(value && value.useFactory); 58497} 58498 58499function isTypeProvider(value) { 58500 return typeof value === 'function'; 58501} 58502 58503function isClassProvider(value) { 58504 return !!value.useClass; 58505} 58506/** 58507 * @license 58508 * Copyright Google LLC All Rights Reserved. 58509 * 58510 * Use of this source code is governed by an MIT-style license that can be 58511 * found in the LICENSE file at https://angular.io/license 58512 */ 58513 58514/** 58515 * An internal token whose presence in an injector indicates that the injector should treat itself 58516 * as a root scoped injector when processing requests for unknown tokens which may indicate 58517 * they are provided in the root scope. 58518 */ 58519 58520 58521const INJECTOR_SCOPE = new InjectionToken('Set Injector scope.'); 58522/** 58523 * @license 58524 * Copyright Google LLC All Rights Reserved. 58525 * 58526 * Use of this source code is governed by an MIT-style license that can be 58527 * found in the LICENSE file at https://angular.io/license 58528 */ 58529 58530/** 58531 * Marker which indicates that a value has not yet been created from the factory function. 58532 */ 58533 58534const NOT_YET = {}; 58535/** 58536 * Marker which indicates that the factory function for a token is in the process of being called. 58537 * 58538 * If the injector is asked to inject a token with its value set to CIRCULAR, that indicates 58539 * injection of a dependency has recursively attempted to inject the original token, and there is 58540 * a circular dependency among the providers. 58541 */ 58542 58543const CIRCULAR = {}; 58544/** 58545 * A lazily initialized NullInjector. 58546 */ 58547 58548let NULL_INJECTOR$1 = undefined; 58549 58550function getNullInjector() { 58551 if (NULL_INJECTOR$1 === undefined) { 58552 NULL_INJECTOR$1 = new NullInjector(); 58553 } 58554 58555 return NULL_INJECTOR$1; 58556} 58557/** 58558 * An `Injector` that's part of the environment injector hierarchy, which exists outside of the 58559 * component tree. 58560 * 58561 * @developerPreview 58562 */ 58563 58564 58565class EnvironmentInjector {} 58566 58567class R3Injector extends EnvironmentInjector { 58568 constructor(providers, parent, source, scopes) { 58569 super(); 58570 this.parent = parent; 58571 this.source = source; 58572 this.scopes = scopes; 58573 /** 58574 * Map of tokens to records which contain the instances of those tokens. 58575 * - `null` value implies that we don't have the record. Used by tree-shakable injectors 58576 * to prevent further searches. 58577 */ 58578 58579 this.records = new Map(); 58580 /** 58581 * Set of values instantiated by this injector which contain `ngOnDestroy` lifecycle hooks. 58582 */ 58583 58584 this._ngOnDestroyHooks = new Set(); 58585 this._onDestroyHooks = []; 58586 this._destroyed = false; // Start off by creating Records for every provider. 58587
58588 forEachSingleProvider(providers, provider => this.processProvider(provider)); // Make sure the INJECTOR token provides this injector. 58589 58590 this.records.set(INJECTOR, makeRecord(undefined, this)); // And `EnvironmentInjector` if the current injector is supposed to be env-scoped. 58591 58592 if (scopes.has('environment')) { 58593 this.records.set(EnvironmentInjector, makeRecord(undefined, this)); 58594 } // Detect whether this injector has the APP_ROOT_SCOPE token and thus should provide 58595 // any injectable scoped to APP_ROOT_SCOPE. 58596 58597 58598 const record = this.records.get(INJECTOR_SCOPE); 58599 58600 if (record != null && typeof record.value === 'string') { 58601 this.scopes.add(record.value); 58602 } 58603 58604 this.injectorDefTypes = new Set(this.get(INJECTOR_DEF_TYPES.multi, EMPTY_ARRAY, InjectFlags.Self)); 58605 } 58606 /** 58607 * Flag indicating that this injector was previously destroyed. 58608 */ 58609 58610 58611 get destroyed() { 58612 return this._destroyed; 58613 } 58614 /** 58615 * Destroy the injector and release references to every instance or provider associated with it. 58616 * 58617 * Also calls the `OnDestroy` lifecycle hooks of every instance that was created for which a 58618 * hook was found. 58619 */ 58620 58621 58622 destroy() { 58623 this.assertNotDestroyed(); // Set destroyed = true first, in case lifecycle hooks re-enter destroy(). 58624 58625 this._destroyed = true; 58626 58627 try { 58628 // Call all the lifecycle hooks. 58629 for (const service of this._ngOnDestroyHooks) { 58630 service.ngOnDestroy(); 58631 } 58632 58633 for (const hook of this._onDestroyHooks) { 58634 hook(); 58635 } 58636 } finally { 58637 // Release all references. 58638 this.records.clear(); 58639 58640 this._ngOnDestroyHooks.clear(); 58641 58642 this.injectorDefTypes.clear(); 58643 this._onDestroyHooks.length = 0; 58644 } 58645 } 58646 58647 onDestroy(callback) { 58648 this._onDestroyHooks.push(callback); 58649 } 58650 58651 runInContext(fn) { 58652 this.assertNotDestroyed(); 58653 const previousInjector = setCurrentInjector(this); 58654 const previousInjectImplementation = setInjectImplementation(undefined); 58655 58656 try { 58657 return fn(); 58658 } finally { 58659 setCurrentInjector(previousInjector); 58660 setInjectImplementation(previousInjectImplementation); 58661 } 58662 } 58663 58664 get(token, notFoundValue = THROW_IF_NOT_FOUND, flags = InjectFlags.Default) { 58665 this.assertNotDestroyed(); // Set the injection context. 58666 58667 const previousInjector = setCurrentInjector(this); 58668 const previousInjectImplementation = setInjectImplementation(undefined); 58669 58670 try { 58671 // Check for the SkipSelf flag. 58672 if (!(flags & InjectFlags.SkipSelf)) { 58673 // SkipSelf isn't set, check if the record belongs to this injector. 58674 let record = this.records.get(token); 58675 58676 if (record === undefined) { 58677 // No record, but maybe the token is scoped to this injector. Look for an injectable 58678 // def with a scope matching this injector. 58679 const def = couldBeInjectableType(token) && getInjectableDef(token); 58680 58681 if (def && this.injectableDefInScope(def)) { 58682 // Found an injectable def and it's scoped to this injector. Pretend as if it was here 58683 // all along. 58684 record = makeRecord(injectableDefOrInjectorDefFactory(token), NOT_YET); 58685 } else { 58686 record = null; 58687 } 58688 58689 this.records.set(token, record); 58690 } // If a record was found, get the instance for it and return it. 58691 58692 58693 if (record != null 58694 /* NOT null || undefined */ 58695 ) { 58696 return this.hydrate(token, record); 58697 } 58698 } // Select the next injector based on the Self flag - if self is set, the next injector is 58699 // the NullInjector, otherwise it's the parent. 58700 58701 58702 const nextInjector = !(flags & InjectFlags.Self) ? this.parent : getNullInjector(); // Set the notFoundValue based on the Optional flag - if optional is set and notFoundValue 58703 // is undefined, the value is null, otherwise it's the notFoundValue. 58704 58705 notFoundValue = flags & InjectFlags.Optional && notFoundValue === THROW_IF_NOT_FOUND ? null : notFoundValue; 58706 return nextInjector.get(token, notFoundValue); 58707 } catch (e) { 58708 if (e.name === 'NullInjectorError') { 58709 const path = e[NG_TEMP_TOKEN_PATH] = e[NG_TEMP_TOKEN_PATH] || []; 58710 path.unshift(stringify(token)); 58711 58712 if (previousInjector) { 58713 // We still have a parent injector, keep throwing 58714 throw e; 58715 } else { 58716 // Format & throw the final error message when we don't have any previous injector 58717 return catchInjectorError(e, token, 'R3InjectorError', this.source); 58718 } 58719 } else { 58720 throw e; 58721 } 58722 } finally { 58723 // Lastly, restore the previous injection context. 58724 setInjectImplementation(previousInjectImplementation); 58725 setCurrentInjector(previousInjector); 58726 } 58727 } 58728 /** @internal */ 58729 58730
58731 resolveInjectorInitializers() { 58732 const previousInjector = setCurrentInjector(this); 58733 const previousInjectImplementation = setInjectImplementation(undefined); 58734 58735 try { 58736 const initializers = this.get(ENVIRONMENT_INITIALIZER.multi, EMPTY_ARRAY, InjectFlags.Self); 58737 58738 if (ngDevMode && !Array.isArray(initializers)) { 58739 throw new RuntimeError(209 58740 /* RuntimeErrorCode.INVALID_MULTI_PROVIDER */ 58741 , 'Unexpected type of the `ENVIRONMENT_INITIALIZER` token value ' + `(expected an array, but got ${typeof initializers}). ` + 'Please check that the `ENVIRONMENT_INITIALIZER` token is configured as a ' + '`multi: true` provider.'); 58742 } 58743 58744 for (const initializer of initializers) { 58745 initializer(); 58746 } 58747 } finally { 58748 setCurrentInjector(previousInjector); 58749 setInjectImplementation(previousInjectImplementation); 58750 } 58751 } 58752 58753 toString() { 58754 const tokens = []; 58755 const records = this.records; 58756 58757 for (const token of records.keys()) { 58758 tokens.push(stringify(token)); 58759 } 58760 58761 return `R3Injector[${tokens.join(', ')}]`; 58762 } 58763 58764 assertNotDestroyed() { 58765 if (this._destroyed) { 58766 throw new RuntimeError(205 58767 /* RuntimeErrorCode.INJECTOR_ALREADY_DESTROYED */ 58768 , ngDevMode && 'Injector has already been destroyed.'); 58769 } 58770 } 58771 /** 58772 * Process a `SingleProvider` and add it. 58773 */ 58774 58775 58776 processProvider(provider) { 58777 // Determine the token from the provider. Either it's its own token, or has a {provide: ...} 58778 // property. 58779 provider = resolveForwardRef(provider); 58780 let token = isTypeProvider(provider) ? provider : resolveForwardRef(provider && provider.provide); // Construct a `Record` for the provider. 58781 58782 const record = providerToRecord(provider); 58783 58784 if (!isTypeProvider(provider) && provider.multi === true) { 58785 // If the provider indicates that it's a multi-provider, process it specially. 58786 // First check whether it's been defined already. 58787 let multiRecord = this.records.get(token); 58788 58789 if (multiRecord) { 58790 // It has. Throw a nice error if 58791 if (ngDevMode && multiRecord.multi === undefined) { 58792 throwMixedMultiProviderError(); 58793 } 58794 } else { 58795 multiRecord = makeRecord(undefined, NOT_YET, true); 58796 58797 multiRecord.factory = () => injectArgs(multiRecord.multi); 58798 58799 this.records.set(token, multiRecord); 58800 } 58801 58802 token = provider; 58803 multiRecord.multi.push(provider); 58804 } else { 58805 const existing = this.records.get(token); 58806 58807 if (ngDevMode && existing && existing.multi !== undefined) { 58808 throwMixedMultiProviderError(); 58809 } 58810 } 58811 58812 this.records.set(token, record); 58813 } 58814 58815 hydrate(token, record) { 58816 if (ngDevMode && record.value === CIRCULAR) { 58817 throwCyclicDependencyError(stringify(token)); 58818 } else if (record.value === NOT_YET) { 58819 record.value = CIRCULAR; 58820 record.value = record.factory(); 58821 } 58822 58823 if (typeof record.value === 'object' && record.value && hasOnDestroy(record.value)) { 58824 this._ngOnDestroyHooks.add(record.value); 58825 } 58826 58827 return record.value; 58828 } 58829 58830 injectableDefInScope(def) { 58831 if (!def.providedIn) { 58832 return false; 58833 } 58834 58835 const providedIn = resolveForwardRef(def.providedIn); 58836 58837 if (typeof providedIn === 'string') { 58838 return providedIn === 'any' || this.scopes.has(providedIn); 58839 } else { 58840 return this.injectorDefTypes.has(providedIn); 58841 } 58842 } 58843 58844} 58845 58846function injectableDefOrInjectorDefFactory(token) { 58847 // Most tokens will have an injectable def directly on them, which specifies a factory directly. 58848 const injectableDef = getInjectableDef(token); 58849 const factory = injectableDef !== null ? injectableDef.factory : getFactoryDef(token); 58850 58851 if (factory !== null) { 58852 return factory; 58853 } // InjectionTokens should have an injectable def (ɵprov) and thus should be handled above. 58854 // If it's missing that, it's an error. 58855 58856 58857 if (token instanceof InjectionToken) { 58858 throw new RuntimeError(204 58859 /* RuntimeErrorCode.INVALID_INJECTION_TOKEN */ 58860 , ngDevMode && `Token ${stringify(token)} is missing a ɵprov definition.`); 58861 } // Undecorated types can sometimes be created if they have no constructor arguments. 58862 58863 58864 if (token instanceof Function) { 58865 return getUndecoratedInjectableFactory(token); 58866 } // There was no way to resolve a factory for this token. 58867 58868 58869 throw new RuntimeError(204 58870 /* RuntimeErrorCode.INVALID_INJECTION_TOKEN */ 58871 , ngDevMode && 'unreachable'); 58872} 58873 58874function getUndecoratedInjectableFactory(token) { 58875 // If the token has parameters then it has dependencies that we cannot resolve implicitly. 58876 const paramLength = token.length; 58877 58878 if (paramLength > 0) { 58879 const args = newArray(paramLength, '?'); 58880 throw new RuntimeError(204 58881 /* RuntimeErrorCode.INVALID_INJECTION_TOKEN */ 58882 , ngDevMode && `Can't resolve all parameters for ${stringify(token)}: (${args.join(', ')}).`); 58883 } // The constructor function appears to have no parameters. 58884 // This might be because it inherits from a super-class. In which case, use an injectable 58885 // def from an ancestor if there is one.
58886 // Otherwise this really is a simple class with no dependencies, so return a factory that 58887 // just instantiates the zero-arg constructor. 58888 58889 58890 const inheritedInjectableDef = getInheritedInjectableDef(token); 58891 58892 if (inheritedInjectableDef !== null) { 58893 return () => inheritedInjectableDef.factory(token); 58894 } else { 58895 return () => new token(); 58896 } 58897} 58898 58899function providerToRecord(provider) { 58900 if (isValueProvider(provider)) { 58901 return makeRecord(undefined, provider.useValue); 58902 } else { 58903 const factory = providerToFactory(provider); 58904 return makeRecord(factory, NOT_YET); 58905 } 58906} 58907/** 58908 * Converts a `SingleProvider` into a factory function. 58909 * 58910 * @param provider provider to convert to factory 58911 */ 58912 58913 58914function providerToFactory(provider, ngModuleType, providers) { 58915 let factory = undefined; 58916 58917 if (ngDevMode && isImportedNgModuleProviders(provider)) { 58918 throwInvalidProviderError(undefined, providers, provider); 58919 } 58920 58921 if (isTypeProvider(provider)) { 58922 const unwrappedProvider = resolveForwardRef(provider); 58923 return getFactoryDef(unwrappedProvider) || injectableDefOrInjectorDefFactory(unwrappedProvider); 58924 } else { 58925 if (isValueProvider(provider)) { 58926 factory = () => resolveForwardRef(provider.useValue); 58927 } else if (isFactoryProvider(provider)) { 58928 factory = () => provider.useFactory(...injectArgs(provider.deps || [])); 58929 } else if (isExistingProvider(provider)) { 58930 factory = () => ɵɵinject(resolveForwardRef(provider.useExisting)); 58931 } else { 58932 const classRef = resolveForwardRef(provider && (provider.useClass || provider.provide)); 58933 58934 if (ngDevMode && !classRef) { 58935 throwInvalidProviderError(ngModuleType, providers, provider); 58936 } 58937 58938 if (hasDeps(provider)) { 58939 factory = () => new classRef(...injectArgs(provider.deps)); 58940 } else { 58941 return getFactoryDef(classRef) || injectableDefOrInjectorDefFactory(classRef); 58942 } 58943 } 58944 } 58945 58946 return factory; 58947} 58948 58949function makeRecord(factory, value, multi = false) { 58950 return { 58951 factory: factory, 58952 value: value, 58953 multi: multi ? [] : undefined 58954 }; 58955} 58956 58957function hasDeps(value) { 58958 return !!value.deps; 58959} 58960 58961function hasOnDestroy(value) { 58962 return value !== null && typeof value === 'object' && typeof value.ngOnDestroy === 'function'; 58963} 58964 58965function couldBeInjectableType(value) { 58966 return typeof value === 'function' || typeof value === 'object' && value instanceof InjectionToken; 58967} 58968 58969function isImportedNgModuleProviders(provider) { 58970 return !!provider.ɵproviders; 58971} 58972 58973function forEachSingleProvider(providers, fn) { 58974 for (const provider of providers) { 58975 if (Array.isArray(provider)) { 58976 forEachSingleProvider(provider, fn); 58977 } else if (isImportedNgModuleProviders(provider)) { 58978 forEachSingleProvider(provider.ɵproviders, fn); 58979 } else { 58980 fn(provider); 58981 } 58982 } 58983} 58984/** 58985 * @license 58986 * Copyright Google LLC All Rights Reserved. 58987 * 58988 * Use of this source code is governed by an MIT-style license that can be 58989 * found in the LICENSE file at https://angular.io/license 58990 */ 58991 58992/** 58993 * Represents a component created by a `ComponentFactory`. 58994 * Provides access to the component instance and related objects, 58995 * and provides the means of destroying the instance. 58996 * 58997 * @publicApi 58998 */ 58999 59000 59001class ComponentRef$1 {} 59002/** 59003 * Base class for a factory that can create a component dynamically. 59004 * Instantiate a factory for a given type of component with `resolveComponentFactory()`. 59005 * Use the resulting `ComponentFactory.create()` method to create a component of that type. 59006 * 59007 * @see [Dynamic Components](guide/dynamic-component-loader) 59008 * 59009 * @publicApi 59010 * 59011 * @deprecated Angular no longer requires Component factories. Please use other APIs where 59012 * Component class can be used directly. 59013 */ 59014 59015 59016class ComponentFactory$1 {} 59017/** 59018 * @license 59019 * Copyright Google LLC All Rights Reserved. 59020 * 59021 * Use of this source code is governed by an MIT-style license that can be 59022 * found in the LICENSE file at https://angular.io/license 59023 */ 59024 59025 59026function noComponentFactoryError(component) { 59027 const error = Error(`No component factory found for ${stringify(component)}. Did you add it to @NgModule.entryComponents?`); 59028 error[ERROR_COMPONENT] = component; 59029 return error; 59030} 59031 59032const ERROR_COMPONENT = 'ngComponent'; 59033 59034function getComponent$1(error) { 59035 return error[ERROR_COMPONENT]; 59036} 59037 59038class _NullComponentFactoryResolver { 59039 resolveComponentFactory(component) { 59040 throw noComponentFactoryError(component); 59041 } 59042 59043} 59044/** 59045 * A simple registry that maps `Components` to generated `ComponentFactory` classes 59046 * that can be used to create instances of components. 59047 * Use to obtain the factory for a given component type, 59048 * then use the factory's `create()` method to create a component of that type. 59049 *
59050 * Note: since v13, dynamic component creation via 59051 * [`ViewContainerRef.createComponent`](api/core/ViewContainerRef#createComponent) 59052 * does **not** require resolving component factory: component class can be used directly. 59053 * 59054 * @publicApi 59055 * 59056 * @deprecated Angular no longer requires Component factories. Please use other APIs where 59057 * Component class can be used directly. 59058 */ 59059 59060 59061class ComponentFactoryResolver$1 {} 59062 59063ComponentFactoryResolver$1.NULL = /* @__PURE__ */new _NullComponentFactoryResolver(); 59064/** 59065 * @license 59066 * Copyright Google LLC All Rights Reserved. 59067 * 59068 * Use of this source code is governed by an MIT-style license that can be 59069 * found in the LICENSE file at https://angular.io/license 59070 */ 59071 59072/** 59073 * Creates an ElementRef from the most recent node. 59074 * 59075 * @returns The ElementRef instance to use 59076 */ 59077 59078function injectElementRef() { 59079 return createElementRef(getCurrentTNode(), getLView()); 59080} 59081/** 59082 * Creates an ElementRef given a node. 59083 * 59084 * @param tNode The node for which you'd like an ElementRef 59085 * @param lView The view to which the node belongs 59086 * @returns The ElementRef instance to use 59087 */ 59088 59089 59090function createElementRef(tNode, lView) { 59091 return new ElementRef(getNativeByTNode(tNode, lView)); 59092} 59093/** 59094 * A wrapper around a native element inside of a View. 59095 * 59096 * An `ElementRef` is backed by a render-specific element. In the browser, this is usually a DOM 59097 * element. 59098 * 59099 * @security Permitting direct access to the DOM can make your application more vulnerable to 59100 * XSS attacks. Carefully review any use of `ElementRef` in your code. For more detail, see the 59101 * [Security Guide](https://g.co/ng/security). 59102 * 59103 * @publicApi 59104 */ 59105// Note: We don't expose things like `Injector`, `ViewContainer`, ... here, 59106// i.e. users have to ask for what they need. With that, we can build better analysis tools 59107// and could do better codegen in the future. 59108 59109 59110class ElementRef { 59111 constructor(nativeElement) { 59112 this.nativeElement = nativeElement; 59113 } 59114 59115} 59116/** 59117 * @internal 59118 * @nocollapse 59119 */ 59120 59121 59122ElementRef.__NG_ELEMENT_ID__ = injectElementRef; 59123/** 59124 * Unwraps `ElementRef` and return the `nativeElement`. 59125 * 59126 * @param value value to unwrap 59127 * @returns `nativeElement` if `ElementRef` otherwise returns value as is. 59128 */ 59129 59130function unwrapElementRef(value) { 59131 return value instanceof ElementRef ? value.nativeElement : value; 59132} 59133/** 59134 * @license 59135 * Copyright Google LLC All Rights Reserved. 59136 * 59137 * Use of this source code is governed by an MIT-style license that can be 59138 * found in the LICENSE file at https://angular.io/license 59139 */ 59140 59141 59142const Renderer2Interceptor = new InjectionToken('Renderer2Interceptor'); 59143/** 59144 * Creates and initializes a custom renderer that implements the `Renderer2` base class. 59145 * 59146 * @publicApi 59147 */ 59148 59149class RendererFactory2 {} 59150/** 59151 * Extend this base class to implement custom rendering. By default, Angular 59152 * renders a template into DOM. You can use custom rendering to intercept 59153 * rendering calls, or to render to something other than DOM. 59154 * 59155 * Create your custom renderer using `RendererFactory2`. 59156 * 59157 * Use a custom renderer to bypass Angular's templating and 59158 * make custom UI changes that can't be expressed declaratively. 59159 * For example if you need to set a property or an attribute whose name is 59160 * not statically known, use the `setProperty()` or 59161 * `setAttribute()` method. 59162 * 59163 * @publicApi 59164 */ 59165 59166 59167class Renderer2 {} 59168/** 59169 * @internal 59170 * @nocollapse 59171 */ 59172 59173 59174Renderer2.__NG_ELEMENT_ID__ = () => injectRenderer2(); 59175/** Injects a Renderer2 for the current component. */ 59176 59177 59178function injectRenderer2() { 59179 // We need the Renderer to be based on the component that it's being injected into, however since 59180 // DI happens before we've entered its view, `getLView` will return the parent view instead. 59181 const lView = getLView(); 59182 const tNode = getCurrentTNode(); 59183 const nodeAtIndex = getComponentLViewByIndex(tNode.index, lView); 59184 return (isLView(nodeAtIndex) ? nodeAtIndex : lView)[RENDERER]; 59185} 59186/** 59187 * @license 59188 * Copyright Google LLC All Rights Reserved. 59189 * 59190 * Use of this source code is governed by an MIT-style license that can be 59191 * found in the LICENSE file at https://angular.io/license 59192 */ 59193 59194/** 59195 * Sanitizer is used by the views to sanitize potentially dangerous values. 59196 * 59197 * @publicApi 59198 */ 59199 59200 59201class Sanitizer {} 59202/** @nocollapse */ 59203 59204 59205Sanitizer.ɵprov = ɵɵdefineInjectable({ 59206 token: Sanitizer, 59207 providedIn: 'root', 59208 factory: () => null 59209}); 59210/** 59211 * @license 59212 * Copyright Google LLC All Rights Reserved. 59213 * 59214 * Use of this source code is governed by an MIT-style license that can be 59215 * found in the LICENSE file at https://angular.io/license 59216 */ 59217 59218/** 59219 * @description Represents the version of Angular 59220 * 59221 * @publicApi 59222 */ 59223 59224class Version { 59225 constructor(full) { 59226 this.full = full; 59227 this.major = full.split('.')[0]; 59228 this.minor = full.split('.')[1]; 59229 this.patch = full.split('.').slice(2).join('.'); 59230 } 59231 59232} 59233/** 59234 * @publicApi 59235 */ 59236 59237 59238const VERSION = new Version('14.2.10'); 59239/** 59240 * @license 59241 * Copyright Google LLC All Rights Reserved. 59242 * 59243 * Use of this source code is governed by an MIT-style license that can be 59244 * found in the LICENSE file at https://angular.io/license 59245 */ 59246// This default value is when checking the hierarchy for a token. 59247// 59248// It means both: 59249// - the token is not provided by the current injector, 59250// - only the element injectors should be checked (ie do not check module injectors 59251// 59252// mod1 59253// / 59254// el1 mod2 59255// \ / 59256// el2 59257// 59258// When requesting el2.injector.get(token), we should check in the following order and return the 59259// first found value: 59260// - el2.injector.get(token, default) 59261// - el1.injector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) -> do not check the module 59262// - mod2.injector.get(token, default) 59263 59264const NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR = {}; 59265/** 59266 * @license 59267 * Copyright Google LLC All Rights Reserved. 59268 * 59269 * Use of this source code is governed by an MIT-style license that can be 59270 * found in the LICENSE file at https://angular.io/license 59271 */ 59272 59273/** 59274 * Defines a schema that allows an NgModule to contain the following: 59275 * - Non-Angular elements named with dash case (`-`). 59276 * - Element properties named with dash case (`-`). 59277 * Dash case is the naming convention for custom elements. 59278 * 59279 * @publicApi 59280 */ 59281 59282const CUSTOM_ELEMENTS_SCHEMA = { 59283 name: 'custom-elements' 59284}; 59285/** 59286 * Defines a schema that allows any property on any element. 59287 * 59288 * This schema allows you to ignore the errors related to any unknown elements or properties in a 59289 * template. The usage of this schema is generally discouraged because it prevents useful validation 59290 * and may hide real errors in your template. Consider using the `CUSTOM_ELEMENTS_SCHEMA` instead. 59291 * 59292 * @publicApi 59293 */ 59294
vendor: 11,085 bytes, lines 59295-59545
59295const NO_ERRORS_SCHEMA = { 59296 name: 'no-errors-schema' 59297}; 59298/** 59299 * @license 59300 * Copyright Google LLC All Rights Reserved. 59301 * 59302 * Use of this source code is governed by an MIT-style license that can be 59303 * found in the LICENSE file at https://angular.io/license 59304 */ 59305 59306let shouldThrowErrorOnUnknownElement = false; 59307/** 59308 * Sets a strict mode for JIT-compiled components to throw an error on unknown elements, 59309 * instead of just logging the error. 59310 * (for AOT-compiled ones this check happens at build time). 59311 */ 59312 59313function ɵsetUnknownElementStrictMode(shouldThrow) { 59314 shouldThrowErrorOnUnknownElement = shouldThrow; 59315} 59316/** 59317 * Gets the current value of the strict mode. 59318 */ 59319 59320 59321function ɵgetUnknownElementStrictMode() { 59322 return shouldThrowErrorOnUnknownElement; 59323} 59324 59325let shouldThrowErrorOnUnknownProperty = false; 59326/** 59327 * Sets a strict mode for JIT-compiled components to throw an error on unknown properties, 59328 * instead of just logging the error. 59329 * (for AOT-compiled ones this check happens at build time). 59330 */ 59331 59332function ɵsetUnknownPropertyStrictMode(shouldThrow) { 59333 shouldThrowErrorOnUnknownProperty = shouldThrow; 59334} 59335/** 59336 * Gets the current value of the strict mode. 59337 */ 59338 59339 59340function ɵgetUnknownPropertyStrictMode() { 59341 return shouldThrowErrorOnUnknownProperty; 59342} 59343/** 59344 * Validates that the element is known at runtime and produces 59345 * an error if it's not the case. 59346 * This check is relevant for JIT-compiled components (for AOT-compiled 59347 * ones this check happens at build time). 59348 * 59349 * The element is considered known if either: 59350 * - it's a known HTML element 59351 * - it's a known custom element 59352 * - the element matches any directive 59353 * - the element is allowed by one of the schemas 59354 * 59355 * @param element Element to validate 59356 * @param lView An `LView` that represents a current component that is being rendered 59357 * @param tagName Name of the tag to check 59358 * @param schemas Array of schemas 59359 * @param hasDirectives Boolean indicating that the element matches any directive 59360 */ 59361 59362 59363function validateElementIsKnown(element, lView, tagName, schemas, hasDirectives) { 59364 // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT 59365 // mode where this check happens at compile time. In JIT mode, `schemas` is always present and 59366 // defined as an array (as an empty array in case `schemas` field is not defined) and we should 59367 // execute the check below. 59368 if (schemas === null) return; // If the element matches any directive, it's considered as valid. 59369 59370 if (!hasDirectives && tagName !== null) { 59371 // The element is unknown if it's an instance of HTMLUnknownElement, or it isn't registered 59372 // as a custom element. Note that unknown elements with a dash in their name won't be instances 59373 // of HTMLUnknownElement in browsers that support web components. 59374 const isUnknown = // Note that we can't check for `typeof HTMLUnknownElement === 'function'`, 59375 // because while most browsers return 'function', IE returns 'object'. 59376 typeof HTMLUnknownElement !== 'undefined' && HTMLUnknownElement && element instanceof HTMLUnknownElement || typeof customElements !== 'undefined' && tagName.indexOf('-') > -1 && !customElements.get(tagName); 59377 59378 if (isUnknown && !matchingSchemas(schemas, tagName)) { 59379 const isHostStandalone = isHostComponentStandalone(lView); 59380 const templateLocation = getTemplateLocationDetails(lView); 59381 const schemas = `'${isHostStandalone ? '@Component' : '@NgModule'}.schemas'`; 59382 let message = `'${tagName}' is not a known element${templateLocation}:\n`; 59383 message += `1. If '${tagName}' is an Angular component, then verify that it is ${isHostStandalone ? 'included in the \'@Component.imports\' of this component' : 'a part of an @NgModule where this component is declared'}.\n`; 59384 59385 if (tagName && tagName.indexOf('-') > -1) { 59386 message += `2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the ${schemas} of this component to suppress this message.`; 59387 } else { 59388 message += `2. To allow any element add 'NO_ERRORS_SCHEMA' to the ${schemas} of this component.`; 59389 } 59390 59391 if (shouldThrowErrorOnUnknownElement) { 59392 throw new RuntimeError(304 59393 /* RuntimeErrorCode.UNKNOWN_ELEMENT */ 59394 , message); 59395 } else { 59396 console.error(formatRuntimeError(304 59397 /* RuntimeErrorCode.UNKNOWN_ELEMENT */ 59398 , message)); 59399 } 59400 } 59401 } 59402} 59403/** 59404 * Validates that the property of the element is known at runtime and returns 59405 * false if it's not the case. 59406 * This check is relevant for JIT-compiled components (for AOT-compiled 59407 * ones this check happens at build time). 59408 * 59409 * The property is considered known if either: 59410 * - it's a known property of the element 59411 * - the element is allowed by one of the schemas 59412 * - the property is used for animations 59413 * 59414 * @param element Element to validate 59415 * @param propName Name of the property to check 59416 * @param tagName Name of the tag hosting the property 59417 * @param schemas Array of schemas 59418 */ 59419 59420 59421function isPropertyValid(element, propName, tagName, schemas) { 59422 // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT 59423 // mode where this check happens at compile time. In JIT mode, `schemas` is always present and 59424 // defined as an array (as an empty array in case `schemas` field is not defined) and we should 59425 // execute the check below. 59426 if (schemas === null) return true; // The property is considered valid if the element matches the schema, it exists on the element, 59427 // or it is synthetic, and we are in a browser context (web worker nodes should be skipped). 59428 59429 if (matchingSchemas(schemas, tagName) || propName in element || isAnimationProp(propName)) { 59430 return true; 59431 } // Note: `typeof Node` returns 'function' in most browsers, but on IE it is 'object' so we 59432 // need to account for both here, while being careful with `typeof null` also returning 'object'. 59433 59434 59435 return typeof Node === 'undefined' || Node === null || !(element instanceof Node); 59436} 59437/** 59438 * Logs or throws an error that a property is not supported on an element. 59439 * 59440 * @param propName Name of the invalid property 59441 * @param tagName Name of the tag hosting the property 59442 * @param nodeType Type of the node hosting the property 59443 * @param lView An `LView` that represents a current component 59444 */ 59445 59446 59447function handleUnknownPropertyError(propName, tagName, nodeType, lView) { 59448 // Special-case a situation when a structural directive is applied to 59449 // an `<ng-template>` element, for example: `<ng-template *ngIf="true">`. 59450 // In this case the compiler generates the `ɵɵtemplate` instruction with 59451 // the `null` as the tagName. The directive matching logic at runtime relies 59452 // on this effect (see `isInlineTemplate`), thus using the 'ng-template' as 59453 // a default value of the `tNode.value` is not feasible at this moment. 59454 if (!tagName && nodeType === 4 59455 /* TNodeType.Container */ 59456 ) { 59457 tagName = 'ng-template'; 59458 } 59459 59460 const isHostStandalone = isHostComponentStandalone(lView); 59461 const templateLocation = getTemplateLocationDetails(lView); 59462 let message = `Can't bind to '${propName}' since it isn't a known property of '${tagName}'${templateLocation}.`; 59463 const schemas = `'${isHostStandalone ? '@Component' : '@NgModule'}.schemas'`; 59464 const importLocation = isHostStandalone ? 'included in the \'@Component.imports\' of this component' : 'a part of an @NgModule where this component is declared'; 59465 59466 if (KNOWN_CONTROL_FLOW_DIRECTIVES.has(propName)) { 59467 // Most likely this is a control flow directive (such as `*ngIf`) used in 59468 // a template, but the directive or the `CommonModule` is not imported. 59469 const correspondingImport = KNOWN_CONTROL_FLOW_DIRECTIVES.get(propName); 59470 message += `\nIf the '${propName}' is an Angular control flow directive, ` + `please make sure that either the '${correspondingImport}' directive or the 'CommonModule' is ${importLocation}.`; 59471 } else { 59472 // May be an Angular component, which is not imported/declared? 59473 message += `\n1. If '${tagName}' is an Angular component and it has the ` + `'${propName}' input, then verify that it is ${importLocation}.`; // May be a Web Component? 59474 59475 if (tagName && tagName.indexOf('-') > -1) { 59476 message += `\n2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' ` + `to the ${schemas} of this component to suppress this message.`; 59477 message += `\n3. To allow any property add 'NO_ERRORS_SCHEMA' to ` + `the ${schemas} of this component.`; 59478 } else { 59479 // If it's expected, the error can be suppressed by the `NO_ERRORS_SCHEMA` schema. 59480 message += `\n2. To allow any property add 'NO_ERRORS_SCHEMA' to ` + `the ${schemas} of this component.`; 59481 } 59482 } 59483 59484 reportUnknownPropertyError(message); 59485} 59486 59487function reportUnknownPropertyError(message) { 59488 if (shouldThrowErrorOnUnknownProperty) { 59489 throw new RuntimeError(303 59490 /* RuntimeErrorCode.UNKNOWN_BINDING */ 59491 , message); 59492 } else { 59493 console.error(formatRuntimeError(303 59494 /* RuntimeErrorCode.UNKNOWN_BINDING */ 59495 , message)); 59496 } 59497} 59498/** 59499 * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`) 59500 * and must **not** be used in production bundles. The function makes megamorphic reads, which might 59501 * be too slow for production mode and also it relies on the constructor function being available. 59502 * 59503 * Gets a reference to the host component def (where a current component is declared). 59504 * 59505 * @param lView An `LView` that represents a current component that is being rendered. 59506 */ 59507 59508 59509function getDeclarationComponentDef(lView) { 59510 !ngDevMode && throwError('Must never be called in production mode'); 59511 const declarationLView = lView[DECLARATION_COMPONENT_VIEW]; 59512 const context = declarationLView[CONTEXT]; // Unable to obtain a context. 59513 59514 if (!context) return null; 59515 return context.constructor ? getComponentDef(context.constructor) : null; 59516} 59517/** 59518 * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`) 59519 * and must **not** be used in production bundles. The function makes megamorphic reads, which might 59520 * be too slow for production mode. 59521 * 59522 * Checks if the current component is declared inside of a standalone component template. 59523 * 59524 * @param lView An `LView` that represents a current component that is being rendered. 59525 */ 59526 59527 59528function isHostComponentStandalone(lView) { 59529 !ngDevMode && throwError('Must never be called in production mode'); 59530 const componentDef = getDeclarationComponentDef(lView); // Treat host component as non-standalone if we can't obtain the def. 59531 59532 return !!componentDef?.standalone; 59533} 59534/** 59535 * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`) 59536 * and must **not** be used in production bundles. The function makes megamorphic reads, which might 59537 * be too slow for production mode. 59538 * 59539 * Constructs a string describing the location of the host component template. The function is used 59540 * in dev mode to produce error messages. 59541 * 59542 * @param lView An `LView` that represents a current component that is being rendered. 59543 */ 59544 59545
59546function getTemplateLocationDetails(lView) { 59547 !ngDevMode && throwError('Must never be called in production mode'); 59548 const hostComponentDef = getDeclarationComponentDef(lView); 59549 const componentClassName = hostComponentDef?.type?.name; 59550 return componentClassName ? ` (used in the '${componentClassName}' component template)` : ''; 59551} 59552/** 59553 * The set of known control flow directives and their corresponding imports. 59554 * We use this set to produce a more precises error message with a note 59555 * that the `CommonModule` should also be included. 59556 */ 59557 59558 59559const KNOWN_CONTROL_FLOW_DIRECTIVES = new Map([['ngIf', 'NgIf'], ['ngFor', 'NgFor'], ['ngSwitchCase', 'NgSwitchCase'], ['ngSwitchDefault', 'NgSwitchDefault']]); 59560/** 59561 * Returns true if the tag name is allowed by specified schemas. 59562 * @param schemas Array of schemas 59563 * @param tagName Name of the tag 59564 */ 59565 59566function matchingSchemas(schemas, tagName) { 59567 if (schemas !== null) { 59568 for (let i = 0; i < schemas.length; i++) { 59569 const schema = schemas[i]; 59570 59571 if (schema === NO_ERRORS_SCHEMA || schema === CUSTOM_ELEMENTS_SCHEMA && tagName && tagName.indexOf('-') > -1) { 59572 return true; 59573 } 59574 } 59575 } 59576 59577 return false; 59578} 59579/** 59580 * @license 59581 * Copyright Google LLC All Rights Reserved. 59582 * 59583 * Use of this source code is governed by an MIT-style license that can be 59584 * found in the LICENSE file at https://angular.io/license 59585 */ 59586 59587 59588const ERROR_ORIGINAL_ERROR = 'ngOriginalError'; 59589 59590function wrappedError(message, originalError) { 59591 const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`; 59592 const error = Error(msg); 59593 error[ERROR_ORIGINAL_ERROR] = originalError; 59594 return error; 59595} 59596 59597function getOriginalError(error) { 59598 return error[ERROR_ORIGINAL_ERROR]; 59599} 59600/** 59601 * @license 59602 * Copyright Google LLC All Rights Reserved. 59603 * 59604 * Use of this source code is governed by an MIT-style license that can be 59605 * found in the LICENSE file at https://angular.io/license 59606 */ 59607 59608/** 59609 * Provides a hook for centralized exception handling. 59610 * 59611 * The default implementation of `ErrorHandler` prints error messages to the `console`. To 59612 * intercept error handling, write a custom exception handler that replaces this default as 59613 * appropriate for your app. 59614 * 59615 * @usageNotes 59616 * ### Example 59617 * 59618 * ``` 59619 * class MyErrorHandler implements ErrorHandler { 59620 * handleError(error) { 59621 * // do something with the exception 59622 * } 59623 * } 59624 * 59625 * @NgModule({ 59626 * providers: [{provide: ErrorHandler, useClass: MyErrorHandler}] 59627 * }) 59628 * class MyModule {} 59629 * ``` 59630 * 59631 * @publicApi 59632 */ 59633 59634 59635class ErrorHandler { 59636 constructor() { 59637 /** 59638 * @internal 59639 */ 59640 this._console = console; 59641 } 59642 59643 handleError(error) { 59644 const originalError = this._findOriginalError(error); 59645 59646 this._console.error('ERROR', error); 59647 59648 if (originalError) { 59649 this._console.error('ORIGINAL ERROR', originalError); 59650 } 59651 } 59652 /** @internal */ 59653 59654 59655 _findOriginalError(error) { 59656 let e = error && getOriginalError(error); 59657 59658 while (e && getOriginalError(e)) { 59659 e = getOriginalError(e); 59660 } 59661 59662 return e || null; 59663 } 59664 59665} 59666/** 59667 * @license 59668 * Copyright Google LLC All Rights Reserved. 59669 * 59670 * Use of this source code is governed by an MIT-style license that can be 59671 * found in the LICENSE file at https://angular.io/license 59672 */ 59673 59674/** 59675 * Disallowed strings in the comment. 59676 * 59677 * see: https://html.spec.whatwg.org/multipage/syntax.html#comments 59678 */ 59679 59680 59681const COMMENT_DISALLOWED = /^>|^->|<!--|-->|--!>|<!-$/g; 59682/** 59683 * Delimiter in the disallowed strings which needs to be wrapped with zero with character. 59684 */ 59685 59686const COMMENT_DELIMITER = /(<|>)/; 59687const COMMENT_DELIMITER_ESCAPED = '\u200B$1\u200B'; 59688/** 59689 * Escape the content of comment strings so that it can be safely inserted into a comment node. 59690 * 59691 * The issue is that HTML does not specify any way to escape comment end text inside the comment. 59692 * Consider: `<!-- The way you close a comment is with ">", and "->" at the beginning or by "-->" or 59693 * "--!>" at the end. -->`. Above the `"-->"` is meant to be text not an end to the comment. This 59694 * can be created programmatically through DOM APIs. (`<!--` are also disallowed.) 59695 * 59696 * see: https://html.spec.whatwg.org/multipage/syntax.html#comments 59697 * 59698 * ``` 59699 * div.innerHTML = div.innerHTML 59700 * ``` 59701 * 59702 * One would expect that the above code would be safe to do, but it turns out that because comment 59703 * text is not escaped, the comment may contain text which will prematurely close the comment 59704 * opening up the application for XSS attack. (In SSR we programmatically create comment nodes which 59705 * may contain such text and expect them to be safe.) 59706 * 59707 * This function escapes the comment text by looking for comment delimiters (`<` and `>`) and 59708 * surrounding them with `_>_` where the `_` is a zero width space `\u200B`. The result is that if a 59709 * comment contains any of the comment start/end delimiters (such as `<!--`, `-->` or `--!>`) the 59710 * text it will render normally but it will not cause the HTML parser to close/open the comment. 59711 * 59712 * @param value text to make safe for comment node by escaping the comment open/close character 59713 * sequence. 59714 */ 59715 59716function escapeCommentText(value) { 59717 return value.replace(COMMENT_DISALLOWED, text => text.replace(COMMENT_DELIMITER, COMMENT_DELIMITER_ESCAPED)); 59718} 59719/** 59720 * @license 59721 * Copyright Google LLC All Rights Reserved. 59722 * 59723 * Use of this source code is governed by an MIT-style license that can be 59724 * found in the LICENSE file at https://angular.io/license 59725 */ 59726 59727 59728function normalizeDebugBindingName(name) { 59729 // Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers 59730 name = camelCaseToDashCase(name.replace(/[$@]/g, '_')); 59731 return `ng-reflect-${name}`; 59732} 59733 59734const CAMEL_CASE_REGEXP = /([A-Z])/g; 59735 59736function camelCaseToDashCase(input) { 59737 return input.replace(CAMEL_CASE_REGEXP, (...m) => '-' + m[1].toLowerCase()); 59738} 59739 59740function normalizeDebugBindingValue(value) { 59741 try { 59742 // Limit the size of the value as otherwise the DOM just gets polluted.
59743 return value != null ? value.toString().slice(0, 30) : value; 59744 } catch (e) { 59745 return '[ERROR] Exception while trying to serialize the value'; 59746 } 59747} 59748/** 59749 * @license 59750 * Copyright Google LLC All Rights Reserved. 59751 * 59752 * Use of this source code is governed by an MIT-style license that can be 59753 * found in the LICENSE file at https://angular.io/license 59754 */ 59755// Keeps track of the currently-active LViews. 59756 59757 59758const TRACKED_LVIEWS = new Map(); // Used for generating unique IDs for LViews. 59759 59760let uniqueIdCounter = 0; 59761/** Gets a unique ID that can be assigned to an LView. */ 59762 59763function getUniqueLViewId() { 59764 return uniqueIdCounter++; 59765} 59766/** Starts tracking an LView. */ 59767 59768 59769function registerLView(lView) { 59770 ngDevMode && assertNumber(lView[ID], 'LView must have an ID in order to be registered'); 59771 TRACKED_LVIEWS.set(lView[ID], lView); 59772} 59773/** Gets an LView by its unique ID. */ 59774 59775 59776function getLViewById(id) { 59777 ngDevMode && assertNumber(id, 'ID used for LView lookup must be a number'); 59778 return TRACKED_LVIEWS.get(id) || null; 59779} 59780/** Stops tracking an LView. */ 59781 59782 59783function unregisterLView(lView) { 59784 ngDevMode && assertNumber(lView[ID], 'Cannot stop tracking an LView that does not have an ID'); 59785 TRACKED_LVIEWS.delete(lView[ID]); 59786} 59787/** 59788 * @license 59789 * Copyright Google LLC All Rights Reserved. 59790 * 59791 * Use of this source code is governed by an MIT-style license that can be 59792 * found in the LICENSE file at https://angular.io/license 59793 */ 59794 59795/** 59796 * The internal view context which is specific to a given DOM element, directive or 59797 * component instance. Each value in here (besides the LView and element node details) 59798 * can be present, null or undefined. If undefined then it implies the value has not been 59799 * looked up yet, otherwise, if null, then a lookup was executed and nothing was found. 59800 * 59801 * Each value will get filled when the respective value is examined within the getContext 59802 * function. The component, element and each directive instance will share the same instance 59803 * of the context. 59804 */ 59805 59806 59807class LContext { 59808 constructor( 59809 /** 59810 * ID of the component's parent view data. 59811 */ 59812 lViewId, 59813 /** 59814 * The index instance of the node. 59815 */ 59816 nodeIndex, 59817 /** 59818 * The instance of the DOM node that is attached to the lNode. 59819 */ 59820 native) { 59821 this.lViewId = lViewId; 59822 this.nodeIndex = nodeIndex; 59823 this.native = native; 59824 } 59825 /** Component's parent view data. */ 59826 59827 59828 get lView() { 59829 return getLViewById(this.lViewId); 59830 } 59831 59832} 59833/** 59834 * @license 59835 * Copyright Google LLC All Rights Reserved. 59836 * 59837 * Use of this source code is governed by an MIT-style license that can be 59838 * found in the LICENSE file at https://angular.io/license 59839 */ 59840 59841/** 59842 * Returns the matching `LContext` data for a given DOM node, directive or component instance. 59843 * 59844 * This function will examine the provided DOM element, component, or directive instance\'s 59845 * monkey-patched property to derive the `LContext` data. Once called then the monkey-patched 59846 * value will be that of the newly created `LContext`. 59847 * 59848 * If the monkey-patched value is the `LView` instance then the context value for that 59849 * target will be created and the monkey-patch reference will be updated. Therefore when this 59850 * function is called it may mutate the provided element\'s, component\'s or any of the associated 59851 * directive\'s monkey-patch values. 59852 * 59853 * If the monkey-patch value is not detected then the code will walk up the DOM until an element 59854 * is found which contains a monkey-patch reference. When that occurs then the provided element 59855 * will be updated with a new context (which is then returned). If the monkey-patch value is not 59856 * detected for a component/directive instance then it will throw an error (all components and 59857 * directives should be automatically monkey-patched by ivy). 59858 * 59859 * @param target Component, Directive or DOM Node. 59860 */ 59861 59862 59863function getLContext(target) { 59864 let mpValue = readPatchedData(target); 59865 59866 if (mpValue) { 59867 // only when it's an array is it considered an LView instance 59868 // ... otherwise it's an already constructed LContext instance 59869 if (isLView(mpValue)) { 59870 const lView = mpValue; 59871 let nodeIndex; 59872 let component = undefined; 59873 let directives = undefined; 59874 59875 if (isComponentInstance(target)) { 59876 nodeIndex = findViaComponent(lView, target); 59877 59878 if (nodeIndex == -1) { 59879 throw new Error('The provided component was not found in the application'); 59880 } 59881 59882 component = target; 59883 } else if (isDirectiveInstance(target)) { 59884 nodeIndex = findViaDirective(lView, target); 59885 59886 if (nodeIndex == -1) { 59887 throw new Error('The provided directive was not found in the application'); 59888 } 59889 59890 directives = getDirectivesAtNodeIndex(nodeIndex, lView, false); 59891 } else { 59892 nodeIndex = findViaNativeElement(lView, target); 59893 59894 if (nodeIndex == -1) { 59895 return null; 59896 } 59897 } // the goal is not to fill the entire context full of data because the lookups 59898 // are expensive. Instead, only the target data (the element, component, container, ICU
vendor: 4,954 bytes, lines 59899-60062
59899 // expression or directive details) are filled into the context. If called multiple times 59900 // with different target values then the missing target data will be filled in. 59901 59902 59903 const native = unwrapRNode(lView[nodeIndex]); 59904 const existingCtx = readPatchedData(native); 59905 const context = existingCtx && !Array.isArray(existingCtx) ? existingCtx : createLContext(lView, nodeIndex, native); // only when the component has been discovered then update the monkey-patch 59906 59907 if (component && context.component === undefined) { 59908 context.component = component; 59909 attachPatchData(context.component, context); 59910 } // only when the directives have been discovered then update the monkey-patch 59911 59912 59913 if (directives && context.directives === undefined) { 59914 context.directives = directives; 59915 59916 for (let i = 0; i < directives.length; i++) { 59917 attachPatchData(directives[i], context); 59918 } 59919 } 59920 59921 attachPatchData(context.native, context); 59922 mpValue = context; 59923 } 59924 } else { 59925 const rElement = target; 59926 ngDevMode && assertDomNode(rElement); // if the context is not found then we need to traverse upwards up the DOM 59927 // to find the nearest element that has already been monkey patched with data 59928 59929 let parent = rElement; 59930 59931 while (parent = parent.parentNode) { 59932 const parentContext = readPatchedData(parent); 59933 59934 if (parentContext) { 59935 const lView = Array.isArray(parentContext) ? parentContext : parentContext.lView; // the edge of the app was also reached here through another means 59936 // (maybe because the DOM was changed manually). 59937 59938 if (!lView) { 59939 return null; 59940 } 59941 59942 const index = findViaNativeElement(lView, rElement); 59943 59944 if (index >= 0) { 59945 const native = unwrapRNode(lView[index]); 59946 const context = createLContext(lView, index, native); 59947 attachPatchData(native, context); 59948 mpValue = context; 59949 break; 59950 } 59951 } 59952 } 59953 } 59954 59955 return mpValue || null; 59956} 59957/** 59958 * Creates an empty instance of a `LContext` context 59959 */ 59960 59961 59962function createLContext(lView, nodeIndex, native) { 59963 return new LContext(lView[ID], nodeIndex, native); 59964} 59965/** 59966 * Takes a component instance and returns the view for that component. 59967 * 59968 * @param componentInstance 59969 * @returns The component's view 59970 */ 59971 59972 59973function getComponentViewByInstance(componentInstance) { 59974 let patchedData = readPatchedData(componentInstance); 59975 let lView; 59976 59977 if (isLView(patchedData)) { 59978 const contextLView = patchedData; 59979 const nodeIndex = findViaComponent(contextLView, componentInstance); 59980 lView = getComponentLViewByIndex(nodeIndex, contextLView); 59981 const context = createLContext(contextLView, nodeIndex, lView[HOST]); 59982 context.component = componentInstance; 59983 attachPatchData(componentInstance, context); 59984 attachPatchData(context.native, context); 59985 } else { 59986 const context = patchedData; 59987 const contextLView = context.lView; 59988 ngDevMode && assertLView(contextLView); 59989 lView = getComponentLViewByIndex(context.nodeIndex, contextLView); 59990 } 59991 59992 return lView; 59993} 59994/** 59995 * This property will be monkey-patched on elements, components and directives. 59996 */ 59997 59998 59999const MONKEY_PATCH_KEY_NAME = '__ngContext__'; 60000/** 60001 * Assigns the given data to the given target (which could be a component, 60002 * directive or DOM node instance) using monkey-patching. 60003 */ 60004 60005function attachPatchData(target, data) { 60006 ngDevMode && assertDefined(target, 'Target expected'); // Only attach the ID of the view in order to avoid memory leaks (see #41047). We only do this 60007 // for `LView`, because we have control over when an `LView` is created and destroyed, whereas 60008 // we can't know when to remove an `LContext`. 60009 60010 if (isLView(data)) { 60011 target[MONKEY_PATCH_KEY_NAME] = data[ID]; 60012 registerLView(data); 60013 } else { 60014 target[MONKEY_PATCH_KEY_NAME] = data; 60015 } 60016} 60017/** 60018 * Returns the monkey-patch value data present on the target (which could be 60019 * a component, directive or a DOM node). 60020 */ 60021 60022 60023function readPatchedData(target) { 60024 ngDevMode && assertDefined(target, 'Target expected'); 60025 const data = target[MONKEY_PATCH_KEY_NAME]; 60026 return typeof data === 'number' ? getLViewById(data) : data || null; 60027} 60028 60029function readPatchedLView(target) { 60030 const value = readPatchedData(target); 60031 60032 if (value) { 60033 return isLView(value) ? value : value.lView; 60034 } 60035 60036 return null; 60037} 60038 60039function isComponentInstance(instance) { 60040 return instance && instance.constructor && instance.constructor.ɵcmp; 60041} 60042 60043function isDirectiveInstance(instance) { 60044 return instance && instance.constructor && instance.constructor.ɵdir; 60045} 60046/** 60047 * Locates the element within the given LView and returns the matching index 60048 */ 60049 60050 60051function findViaNativeElement(lView, target) { 60052 const tView = lView[TVIEW]; 60053 60054 for (let i = HEADER_OFFSET; i < tView.bindingStartIndex; i++) { 60055 if (unwrapRNode(lView[i]) === target) { 60056 return i; 60057 } 60058 } 60059 60060 return -1; 60061} 60062/**
60063 * Locates the next tNode (child, sibling or parent). 60064 */ 60065 60066 60067function traverseNextElement(tNode) { 60068 if (tNode.child) { 60069 return tNode.child; 60070 } else if (tNode.next) { 60071 return tNode.next; 60072 } else { 60073 // Let's take the following template: <div><span>text</span></div><component/> 60074 // After checking the text node, we need to find the next parent that has a "next" TNode, 60075 // in this case the parent `div`, so that we can find the component. 60076 while (tNode.parent && !tNode.parent.next) { 60077 tNode = tNode.parent; 60078 } 60079 60080 return tNode.parent && tNode.parent.next; 60081 } 60082} 60083/** 60084 * Locates the component within the given LView and returns the matching index 60085 */ 60086 60087 60088function findViaComponent(lView, componentInstance) { 60089 const componentIndices = lView[TVIEW].components; 60090 60091 if (componentIndices) { 60092 for (let i = 0; i < componentIndices.length; i++) { 60093 const elementComponentIndex = componentIndices[i]; 60094 const componentView = getComponentLViewByIndex(elementComponentIndex, lView); 60095 60096 if (componentView[CONTEXT] === componentInstance) { 60097 return elementComponentIndex; 60098 } 60099 } 60100 } else { 60101 const rootComponentView = getComponentLViewByIndex(HEADER_OFFSET, lView); 60102 const rootComponent = rootComponentView[CONTEXT]; 60103 60104 if (rootComponent === componentInstance) { 60105 // we are dealing with the root element here therefore we know that the 60106 // element is the very first element after the HEADER data in the lView 60107 return HEADER_OFFSET; 60108 } 60109 } 60110 60111 return -1; 60112} 60113/** 60114 * Locates the directive within the given LView and returns the matching index 60115 */ 60116 60117 60118function findViaDirective(lView, directiveInstance) { 60119 // if a directive is monkey patched then it will (by default) 60120 // have a reference to the LView of the current view. The 60121 // element bound to the directive being search lives somewhere 60122 // in the view data. We loop through the nodes and check their 60123 // list of directives for the instance. 60124 let tNode = lView[TVIEW].firstChild; 60125 60126 while (tNode) { 60127 const directiveIndexStart = tNode.directiveStart; 60128 const directiveIndexEnd = tNode.directiveEnd; 60129 60130 for (let i = directiveIndexStart; i < directiveIndexEnd; i++) { 60131 if (lView[i] === directiveInstance) { 60132 return tNode.index; 60133 } 60134 } 60135 60136 tNode = traverseNextElement(tNode); 60137 } 60138 60139 return -1; 60140} 60141/** 60142 * Returns a list of directives extracted from the given view based on the 60143 * provided list of directive index values. 60144 * 60145 * @param nodeIndex The node index 60146 * @param lView The target view data 60147 * @param includeComponents Whether or not to include components in returned directives 60148 */ 60149 60150 60151function getDirectivesAtNodeIndex(nodeIndex, lView, includeComponents) { 60152 const tNode = lView[TVIEW].data[nodeIndex]; 60153 let directiveStartIndex = tNode.directiveStart; 60154 if (directiveStartIndex == 0) return EMPTY_ARRAY; 60155 const directiveEndIndex = tNode.directiveEnd; 60156 if (!includeComponents && tNode.flags & 2 60157 /* TNodeFlags.isComponentHost */ 60158 ) directiveStartIndex++; 60159 return lView.slice(directiveStartIndex, directiveEndIndex); 60160} 60161 60162function getComponentAtNodeIndex(nodeIndex, lView) { 60163 const tNode = lView[TVIEW].data[nodeIndex]; 60164 let directiveStartIndex = tNode.directiveStart; 60165 return tNode.flags & 2 60166 /* TNodeFlags.isComponentHost */ 60167 ? lView[directiveStartIndex] : null; 60168} 60169/** 60170 * Returns a map of local references (local reference name => element or directive instance) that 60171 * exist on a given element. 60172 */ 60173 60174 60175function discoverLocalRefs(lView, nodeIndex) { 60176 const tNode = lView[TVIEW].data[nodeIndex]; 60177 60178 if (tNode && tNode.localNames) { 60179 const result = {}; 60180 let localIndex = tNode.index + 1; 60181 60182 for (let i = 0; i < tNode.localNames.length; i += 2) { 60183 result[tNode.localNames[i]] = lView[localIndex]; 60184 localIndex++; 60185 } 60186 60187 return result; 60188 } 60189 60190 return null; 60191} 60192/** 60193 * @license 60194 * Copyright Google LLC All Rights Reserved. 60195 * 60196 * Use of this source code is governed by an MIT-style license that can be 60197 * found in the LICENSE file at https://angular.io/license 60198 */ 60199 60200/** 60201 * 60202 * @codeGenApi 60203 */ 60204 60205 60206function ɵɵresolveWindow(element) { 60207 return element.ownerDocument.defaultView; 60208} 60209/** 60210 * 60211 * @codeGenApi 60212 */ 60213 60214 60215function ɵɵresolveDocument(element) { 60216 return element.ownerDocument; 60217} 60218/** 60219 * 60220 * @codeGenApi 60221 */ 60222 60223 60224function ɵɵresolveBody(element) { 60225 return element.ownerDocument.body; 60226} 60227/** 60228 * The special delimiter we use to separate property names, prefixes, and suffixes 60229 * in property binding metadata. See storeBindingMetadata(). 60230 * 60231 * We intentionally use the Unicode "REPLACEMENT CHARACTER" (U+FFFD) as a delimiter 60232 * because it is a very uncommon character that is unlikely to be part of a user's 60233 * property names or interpolation strings. If it is in fact used in a property 60234 * binding, DebugElement.properties will not return the correct value for that 60235 * binding. However, there should be no runtime effect for real applications. 60236 * 60237 * This character is typically rendered as a question mark inside of a diamond. 60238 * See https://en.wikipedia.org/wiki/Specials_(Unicode_block) 60239 * 60240 */ 60241 60242 60243const INTERPOLATION_DELIMITER = `�`; 60244/** 60245 * Unwrap a value which might be behind a closure (for forward declaration reasons). 60246 */ 60247 60248function maybeUnwrapFn(value) { 60249 if (value instanceof Function) { 60250 return value(); 60251 } else { 60252 return value; 60253 } 60254} 60255/** 60256 * @license 60257 * Copyright Google LLC All Rights Reserved. 60258 * 60259 * Use of this source code is governed by an MIT-style license that can be 60260 * found in the LICENSE file at https://angular.io/license 60261 */ 60262 60263/** Verifies that a given type is a Standalone Component. */ 60264 60265 60266function assertStandaloneComponentType(type) { 60267 assertComponentDef(type); 60268 const componentDef = getComponentDef(type); 60269 60270 if (!componentDef.standalone) { 60271 throw new RuntimeError(907 60272 /* RuntimeErrorCode.TYPE_IS_NOT_STANDALONE */ 60273 , `The ${stringifyForError(type)} component is not marked as standalone, ` + `but Angular expects to have a standalone component here. ` + `Please make sure the ${stringifyForError(type)} component has ` + `the \`standalone: true\` flag in the decorator.`); 60274 } 60275} 60276/** Verifies whether a given type is a component */ 60277 60278 60279function assertComponentDef(type) { 60280 if (!getComponentDef(type)) { 60281 throw new RuntimeError(906 60282 /* RuntimeErrorCode.MISSING_GENERATED_DEF */ 60283 , `The ${stringifyForError(type)} is not an Angular component, ` + `make sure it has the \`@Component\` decorator.`); 60284 } 60285} 60286/** Called when there are multiple component selectors that match a given node */ 60287 60288 60289function throwMultipleComponentError(tNode, first, second) { 60290 throw new RuntimeError(-300 60291 /* RuntimeErrorCode.MULTIPLE_COMPONENTS_MATCH */ 60292 , `Multiple components match node with tagname ${tNode.value}: ` + `${stringifyForError(first)} and ` + `${stringifyForError(second)}`); 60293} 60294/** Throws an ExpressionChangedAfterChecked error if checkNoChanges mode is on. */ 60295 60296
vendor: 50,051 bytes, lines 60297-61754
60297function throwErrorIfNoChangesMode(creationMode, oldValue, currValue, propName) { 60298 const field = propName ? ` for '${propName}'` : ''; 60299 let msg = `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value${field}: '${oldValue}'. Current value: '${currValue}'.`; 60300 60301 if (creationMode) { 60302 msg += ` It seems like the view has been created after its parent and its children have been dirty checked.` + ` Has it been created in a change detection hook?`; 60303 } 60304 60305 throw new RuntimeError(-100 60306 /* RuntimeErrorCode.EXPRESSION_CHANGED_AFTER_CHECKED */ 60307 , msg); 60308} 60309 60310function constructDetailsForInterpolation(lView, rootIndex, expressionIndex, meta, changedValue) { 60311 const [propName, prefix, ...chunks] = meta.split(INTERPOLATION_DELIMITER); 60312 let oldValue = prefix, 60313 newValue = prefix; 60314 60315 for (let i = 0; i < chunks.length; i++) { 60316 const slotIdx = rootIndex + i; 60317 oldValue += `${lView[slotIdx]}${chunks[i]}`; 60318 newValue += `${slotIdx === expressionIndex ? changedValue : lView[slotIdx]}${chunks[i]}`; 60319 } 60320 60321 return { 60322 propName, 60323 oldValue, 60324 newValue 60325 }; 60326} 60327/** 60328 * Constructs an object that contains details for the ExpressionChangedAfterItHasBeenCheckedError: 60329 * - property name (for property bindings or interpolations) 60330 * - old and new values, enriched using information from metadata 60331 * 60332 * More information on the metadata storage format can be found in `storePropertyBindingMetadata` 60333 * function description. 60334 */ 60335 60336 60337function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValue) { 60338 const tData = lView[TVIEW].data; 60339 const metadata = tData[bindingIndex]; 60340 60341 if (typeof metadata === 'string') { 60342 // metadata for property interpolation 60343 if (metadata.indexOf(INTERPOLATION_DELIMITER) > -1) { 60344 return constructDetailsForInterpolation(lView, bindingIndex, bindingIndex, metadata, newValue); 60345 } // metadata for property binding 60346 60347 60348 return { 60349 propName: metadata, 60350 oldValue, 60351 newValue 60352 }; 60353 } // metadata is not available for this expression, check if this expression is a part of the 60354 // property interpolation by going from the current binding index left and look for a string that 60355 // contains INTERPOLATION_DELIMITER, the layout in tView.data for this case will look like this: 60356 // [..., 'id�Prefix � and � suffix', null, null, null, ...] 60357 60358 60359 if (metadata === null) { 60360 let idx = bindingIndex - 1; 60361 60362 while (typeof tData[idx] !== 'string' && tData[idx + 1] === null) { 60363 idx--; 60364 } 60365 60366 const meta = tData[idx]; 60367 60368 if (typeof meta === 'string') { 60369 const matches = meta.match(new RegExp(INTERPOLATION_DELIMITER, 'g')); // first interpolation delimiter separates property name from interpolation parts (in case of 60370 // property interpolations), so we subtract one from total number of found delimiters 60371 60372 if (matches && matches.length - 1 > bindingIndex - idx) { 60373 return constructDetailsForInterpolation(lView, idx, bindingIndex, meta, newValue); 60374 } 60375 } 60376 } 60377 60378 return { 60379 propName: undefined, 60380 oldValue, 60381 newValue 60382 }; 60383} 60384/** 60385 * @license 60386 * Copyright Google LLC All Rights Reserved. 60387 * 60388 * Use of this source code is governed by an MIT-style license that can be 60389 * found in the LICENSE file at https://angular.io/license 60390 */ 60391 60392/** 60393 * Flags for renderer-specific style modifiers. 60394 * @publicApi 60395 */ 60396 60397 60398var RendererStyleFlags2; 60399 60400(function (RendererStyleFlags2) { 60401 // TODO(misko): This needs to be refactored into a separate file so that it can be imported from 60402 // `node_manipulation.ts` Currently doing the import cause resolution order to change and fails 60403 // the tests. The work around is to have hard coded value in `node_manipulation.ts` for now. 60404 60405 /** 60406 * Marks a style as important. 60407 */ 60408 RendererStyleFlags2[RendererStyleFlags2["Important"] = 1] = "Important"; 60409 /** 60410 * Marks a style as using dash case naming (this-is-dash-case). 60411 */ 60412 60413 RendererStyleFlags2[RendererStyleFlags2["DashCase"] = 2] = "DashCase"; 60414})(RendererStyleFlags2 || (RendererStyleFlags2 = {})); 60415/** 60416 * @license 60417 * Copyright Google LLC All Rights Reserved. 60418 * 60419 * Use of this source code is governed by an MIT-style license that can be 60420 * found in the LICENSE file at https://angular.io/license 60421 */ 60422 60423 60424let _icuContainerIterate; 60425/** 60426 * Iterator which provides ability to visit all of the `TIcuContainerNode` root `RNode`s. 60427 */ 60428 60429 60430function icuContainerIterate(tIcuContainerNode, lView) { 60431 return _icuContainerIterate(tIcuContainerNode, lView); 60432} 60433/** 60434 * Ensures that `IcuContainerVisitor`'s implementation is present. 60435 * 60436 * This function is invoked when i18n instruction comes across an ICU. The purpose is to allow the 60437 * bundler to tree shake ICU logic and only load it if ICU instruction is executed. 60438 */ 60439 60440 60441function ensureIcuContainerVisitorLoaded(loader) { 60442 if (_icuContainerIterate === undefined) { 60443 // Do not inline this function. We want to keep `ensureIcuContainerVisitorLoaded` light, so it 60444 // can be inlined into call-site. 60445 _icuContainerIterate = loader(); 60446 } 60447} 60448/** 60449 * @license 60450 * Copyright Google LLC All Rights Reserved. 60451 * 60452 * Use of this source code is governed by an MIT-style license that can be 60453 * found in the LICENSE file at https://angular.io/license 60454 */ 60455// Note: This hack is necessary so we don't erroneously get a circular dependency 60456// failure based on types. 60457 60458 60459const unusedValueExportToPlacateAjd$4 = 1; 60460/** 60461 * @license 60462 * Copyright Google LLC All Rights Reserved. 60463 * 60464 * Use of this source code is governed by an MIT-style license that can be 60465 * found in the LICENSE file at https://angular.io/license 60466 */ 60467// Note: This hack is necessary so we don't erroneously get a circular dependency 60468// failure based on types. 60469 60470const unusedValueExportToPlacateAjd$3 = 1; 60471/** 60472 * @license 60473 * Copyright Google LLC All Rights Reserved. 60474 * 60475 * Use of this source code is governed by an MIT-style license that can be 60476 * found in the LICENSE file at https://angular.io/license 60477 */ 60478 60479/** 60480 * Gets the parent LView of the passed LView, if the PARENT is an LContainer, will get the parent of 60481 * that LContainer, which is an LView 60482 * @param lView the lView whose parent to get 60483 */ 60484 60485function getLViewParent(lView) { 60486 ngDevMode && assertLView(lView); 60487 const parent = lView[PARENT]; 60488 return isLContainer(parent) ? parent[PARENT] : parent; 60489} 60490/** 60491 * Retrieve the root view from any component or `LView` by walking the parent `LView` until 60492 * reaching the root `LView`. 60493 * 60494 * @param componentOrLView any component or `LView` 60495 */ 60496 60497 60498function getRootView(componentOrLView) { 60499 ngDevMode && assertDefined(componentOrLView, 'component'); 60500 let lView = isLView(componentOrLView) ? componentOrLView : readPatchedLView(componentOrLView); 60501 60502 while (lView && !(lView[FLAGS] & 256 60503 /* LViewFlags.IsRoot */ 60504 )) { 60505 lView = getLViewParent(lView); 60506 } 60507 60508 ngDevMode && assertLView(lView); 60509 return lView; 60510} 60511/** 60512 * Returns the context information associated with the application where the target is situated. It 60513 * does this by walking the parent views until it gets to the root view, then getting the context 60514 * off of that. 60515 * 60516 * @param viewOrComponent the `LView` or component to get the root context for. 60517 */ 60518 60519 60520function getRootContext(viewOrComponent) { 60521 const rootView = getRootView(viewOrComponent); 60522 ngDevMode && assertDefined(rootView[CONTEXT], 'Root view has no context. Perhaps it is disconnected?'); 60523 return rootView[CONTEXT]; 60524} 60525/** 60526 * Gets the first `LContainer` in the LView or `null` if none exists. 60527 */ 60528 60529 60530function getFirstLContainer(lView) { 60531 return getNearestLContainer(lView[CHILD_HEAD]); 60532} 60533/** 60534 * Gets the next `LContainer` that is a sibling of the given container. 60535 */ 60536 60537 60538function getNextLContainer(container) { 60539 return getNearestLContainer(container[NEXT]); 60540} 60541 60542function getNearestLContainer(viewOrContainer) { 60543 while (viewOrContainer !== null && !isLContainer(viewOrContainer)) { 60544 viewOrContainer = viewOrContainer[NEXT]; 60545 } 60546 60547 return viewOrContainer; 60548} 60549/** 60550 * @license 60551 * Copyright Google LLC All Rights Reserved. 60552 * 60553 * Use of this source code is governed by an MIT-style license that can be 60554 * found in the LICENSE file at https://angular.io/license 60555 */ 60556 60557 60558const unusedValueToPlacateAjd$2 = unusedValueExportToPlacateAjd$7 + unusedValueExportToPlacateAjd$5 + unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd$3 + unusedValueExportToPlacateAjd$8; 60559/** 60560 * NOTE: for performance reasons, the possible actions are inlined within the function instead of 60561 * being passed as an argument. 60562 */ 60563 60564function applyToElementOrContainer(action, renderer, parent, lNodeToHandle, beforeNode) { 60565 // If this slot was allocated for a text node dynamically created by i18n, the text node itself 60566 // won't be created until i18nApply() in the update block, so this node should be skipped. 60567 // For more info, see "ICU expressions should work inside an ngTemplateOutlet inside an ngFor" 60568 // in `i18n_spec.ts`. 60569 if (lNodeToHandle != null) { 60570 let lContainer; 60571 let isComponent = false; // We are expecting an RNode, but in the case of a component or LContainer the `RNode` is 60572 // wrapped in an array which needs to be unwrapped. We need to know if it is a component and if 60573 // it has LContainer so that we can process all of those cases appropriately. 60574 60575 if (isLContainer(lNodeToHandle)) { 60576 lContainer = lNodeToHandle; 60577 } else if (isLView(lNodeToHandle)) { 60578 isComponent = true; 60579 ngDevMode && assertDefined(lNodeToHandle[HOST], 'HOST must be defined for a component LView'); 60580 lNodeToHandle = lNodeToHandle[HOST]; 60581 } 60582 60583 const rNode = unwrapRNode(lNodeToHandle); 60584 60585 if (action === 0 60586 /* WalkTNodeTreeAction.Create */ 60587 && parent !== null) { 60588 if (beforeNode == null) { 60589 nativeAppendChild(renderer, parent, rNode); 60590 } else { 60591 nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true); 60592 } 60593 } else if (action === 1 60594 /* WalkTNodeTreeAction.Insert */ 60595 && parent !== null) { 60596 nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true); 60597 } else if (action === 2 60598 /* WalkTNodeTreeAction.Detach */ 60599 ) { 60600 nativeRemoveNode(renderer, rNode, isComponent); 60601 } else if (action === 3 60602 /* WalkTNodeTreeAction.Destroy */ 60603 ) { 60604 ngDevMode && ngDevMode.rendererDestroyNode++; 60605 renderer.destroyNode(rNode); 60606 } 60607 60608 if (lContainer != null) { 60609 applyContainer(renderer, action, lContainer, parent, beforeNode); 60610 } 60611 } 60612} 60613 60614function createTextNode(renderer, value) { 60615 ngDevMode && ngDevMode.rendererCreateTextNode++; 60616 ngDevMode && ngDevMode.rendererSetText++; 60617 return renderer.createText(value); 60618} 60619 60620function updateTextNode(renderer, rNode, value) { 60621 ngDevMode && ngDevMode.rendererSetText++; 60622 renderer.setValue(rNode, value); 60623} 60624 60625function createCommentNode(renderer, value) { 60626 ngDevMode && ngDevMode.rendererCreateComment++; 60627 return renderer.createComment(escapeCommentText(value)); 60628} 60629/** 60630 * Creates a native element from a tag name, using a renderer. 60631 * @param renderer A renderer to use 60632 * @param name the tag name 60633 * @param namespace Optional namespace for element. 60634 * @returns the element created 60635 */ 60636 60637 60638function createElementNode(renderer, name, namespace) { 60639 ngDevMode && ngDevMode.rendererCreateElement++; 60640 return renderer.createElement(name, namespace); 60641} 60642/** 60643 * Removes all DOM elements associated with a view. 60644 * 60645 * Because some root nodes of the view may be containers, we sometimes need 60646 * to propagate deeply into the nested containers to remove all elements in the 60647 * views beneath it. 60648 * 60649 * @param tView The `TView' of the `LView` from which elements should be added or removed 60650 * @param lView The view from which elements should be added or removed 60651 */ 60652 60653 60654function removeViewFromContainer(tView, lView) { 60655 const renderer = lView[RENDERER]; 60656 applyView(tView, lView, renderer, 2 60657 /* WalkTNodeTreeAction.Detach */ 60658 , null, null); 60659 lView[HOST] = null; 60660 lView[T_HOST] = null; 60661} 60662/** 60663 * Adds all DOM elements associated with a view. 60664 * 60665 * Because some root nodes of the view may be containers, we sometimes need 60666 * to propagate deeply into the nested containers to add all elements in the 60667 * views beneath it. 60668 * 60669 * @param tView The `TView' of the `LView` from which elements should be added or removed 60670 * @param parentTNode The `TNode` where the `LView` should be attached to. 60671 * @param renderer Current renderer to use for DOM manipulations. 60672 * @param lView The view from which elements should be added or removed 60673 * @param parentNativeNode The parent `RElement` where it should be inserted into. 60674 * @param beforeNode The node before which elements should be added, if insert mode 60675 */ 60676 60677 60678function addViewToContainer(tView, parentTNode, renderer, lView, parentNativeNode, beforeNode) { 60679 lView[HOST] = parentNativeNode; 60680 lView[T_HOST] = parentTNode; 60681 applyView(tView, lView, renderer, 1 60682 /* WalkTNodeTreeAction.Insert */ 60683 , parentNativeNode, beforeNode); 60684} 60685/** 60686 * Detach a `LView` from the DOM by detaching its nodes. 60687 * 60688 * @param tView The `TView' of the `LView` to be detached 60689 * @param lView the `LView` to be detached. 60690 */ 60691 60692 60693function renderDetachView(tView, lView) { 60694 applyView(tView, lView, lView[RENDERER], 2 60695 /* WalkTNodeTreeAction.Detach */ 60696 , null, null); 60697} 60698/** 60699 * Traverses down and up the tree of views and containers to remove listeners and 60700 * call onDestroy callbacks. 60701 * 60702 * Notes: 60703 * - Because it's used for onDestroy calls, it needs to be bottom-up. 60704 * - Must process containers instead of their views to avoid splicing 60705 * when views are destroyed and re-added. 60706 * - Using a while loop because it's faster than recursion 60707 * - Destroy only called on movement to sibling or movement to parent (laterally or up) 60708 * 60709 * @param rootView The view to destroy 60710 */ 60711 60712 60713function destroyViewTree(rootView) { 60714 // If the view has no children, we can clean it up and return early. 60715 let lViewOrLContainer = rootView[CHILD_HEAD]; 60716 60717 if (!lViewOrLContainer) { 60718 return cleanUpView(rootView[TVIEW], rootView); 60719 } 60720 60721 while (lViewOrLContainer) { 60722 let next = null; 60723 60724 if (isLView(lViewOrLContainer)) { 60725 // If LView, traverse down to child. 60726 next = lViewOrLContainer[CHILD_HEAD]; 60727 } else { 60728 ngDevMode && assertLContainer(lViewOrLContainer); // If container, traverse down to its first LView. 60729 60730 const firstView = lViewOrLContainer[CONTAINER_HEADER_OFFSET]; 60731 if (firstView) next = firstView; 60732 } 60733 60734 if (!next) { 60735 // Only clean up view when moving to the side or up, as destroy hooks 60736 // should be called in order from the bottom up. 60737 while (lViewOrLContainer && !lViewOrLContainer[NEXT] && lViewOrLContainer !== rootView) { 60738 if (isLView(lViewOrLContainer)) { 60739 cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer); 60740 } 60741 60742 lViewOrLContainer = lViewOrLContainer[PARENT]; 60743 } 60744 60745 if (lViewOrLContainer === null) lViewOrLContainer = rootView; 60746 60747 if (isLView(lViewOrLContainer)) { 60748 cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer); 60749 } 60750 60751 next = lViewOrLContainer && lViewOrLContainer[NEXT]; 60752 } 60753 60754 lViewOrLContainer = next; 60755 } 60756} 60757/** 60758 * Inserts a view into a container. 60759 * 60760 * This adds the view to the container's array of active views in the correct 60761 * position. It also adds the view's elements to the DOM if the container isn't a 60762 * root node of another view (in that case, the view's elements will be added when 60763 * the container's parent view is added later). 60764 * 60765 * @param tView The `TView' of the `LView` to insert 60766 * @param lView The view to insert 60767 * @param lContainer The container into which the view should be inserted 60768 * @param index Which index in the container to insert the child view into 60769 */ 60770 60771 60772function insertView(tView, lView, lContainer, index) { 60773 ngDevMode && assertLView(lView); 60774 ngDevMode && assertLContainer(lContainer); 60775 const indexInContainer = CONTAINER_HEADER_OFFSET + index; 60776 const containerLength = lContainer.length; 60777 60778 if (index > 0) { 60779 // This is a new view, we need to add it to the children. 60780 lContainer[indexInContainer - 1][NEXT] = lView; 60781 } 60782 60783 if (index < containerLength - CONTAINER_HEADER_OFFSET) { 60784 lView[NEXT] = lContainer[indexInContainer]; 60785 addToArray(lContainer, CONTAINER_HEADER_OFFSET + index, lView); 60786 } else { 60787 lContainer.push(lView); 60788 lView[NEXT] = null; 60789 } 60790 60791 lView[PARENT] = lContainer; // track views where declaration and insertion points are different 60792 60793 const declarationLContainer = lView[DECLARATION_LCONTAINER]; 60794 60795 if (declarationLContainer !== null && lContainer !== declarationLContainer) { 60796 trackMovedView(declarationLContainer, lView); 60797 } // notify query that a new view has been added 60798 60799 60800 const lQueries = lView[QUERIES]; 60801 60802 if (lQueries !== null) { 60803 lQueries.insertView(tView); 60804 } // Sets the attached flag 60805 60806 60807 lView[FLAGS] |= 64 60808 /* LViewFlags.Attached */ 60809 ; 60810} 60811/** 60812 * Track views created from the declaration container (TemplateRef) and inserted into a 60813 * different LContainer. 60814 */ 60815 60816 60817function trackMovedView(declarationContainer, lView) { 60818 ngDevMode && assertDefined(lView, 'LView required'); 60819 ngDevMode && assertLContainer(declarationContainer); 60820 const movedViews = declarationContainer[MOVED_VIEWS]; 60821 const insertedLContainer = lView[PARENT]; 60822 ngDevMode && assertLContainer(insertedLContainer); 60823 const insertedComponentLView = insertedLContainer[PARENT][DECLARATION_COMPONENT_VIEW]; 60824 ngDevMode && assertDefined(insertedComponentLView, 'Missing insertedComponentLView'); 60825 const declaredComponentLView = lView[DECLARATION_COMPONENT_VIEW]; 60826 ngDevMode && assertDefined(declaredComponentLView, 'Missing declaredComponentLView'); 60827 60828 if (declaredComponentLView !== insertedComponentLView) { 60829 // At this point the declaration-component is not same as insertion-component; this means that 60830 // this is a transplanted view. Mark the declared lView as having transplanted views so that 60831 // those views can participate in CD. 60832 declarationContainer[HAS_TRANSPLANTED_VIEWS] = true; 60833 } 60834 60835 if (movedViews === null) { 60836 declarationContainer[MOVED_VIEWS] = [lView]; 60837 } else { 60838 movedViews.push(lView); 60839 } 60840} 60841 60842function detachMovedView(declarationContainer, lView) { 60843 ngDevMode && assertLContainer(declarationContainer); 60844 ngDevMode && assertDefined(declarationContainer[MOVED_VIEWS], 'A projected view should belong to a non-empty projected views collection'); 60845 const movedViews = declarationContainer[MOVED_VIEWS]; 60846 const declarationViewIndex = movedViews.indexOf(lView); 60847 const insertionLContainer = lView[PARENT]; 60848 ngDevMode && assertLContainer(insertionLContainer); // If the view was marked for refresh but then detached before it was checked (where the flag 60849 // would be cleared and the counter decremented), we need to decrement the view counter here 60850 // instead. 60851 60852 if (lView[FLAGS] & 512 60853 /* LViewFlags.RefreshTransplantedView */ 60854 ) { 60855 lView[FLAGS] &= ~512 60856 /* LViewFlags.RefreshTransplantedView */ 60857 ; 60858 updateTransplantedViewCount(insertionLContainer, -1); 60859 } 60860 60861 movedViews.splice(declarationViewIndex, 1); 60862} 60863/** 60864 * Detaches a view from a container. 60865 * 60866 * This method removes the view from the container's array of active views. It also 60867 * removes the view's elements from the DOM. 60868 * 60869 * @param lContainer The container from which to detach a view 60870 * @param removeIndex The index of the view to detach 60871 * @returns Detached LView instance. 60872 */ 60873 60874 60875function detachView(lContainer, removeIndex) { 60876 if (lContainer.length <= CONTAINER_HEADER_OFFSET) return; 60877 const indexInContainer = CONTAINER_HEADER_OFFSET + removeIndex; 60878 const viewToDetach = lContainer[indexInContainer]; 60879 60880 if (viewToDetach) { 60881 const declarationLContainer = viewToDetach[DECLARATION_LCONTAINER]; 60882 60883 if (declarationLContainer !== null && declarationLContainer !== lContainer) { 60884 detachMovedView(declarationLContainer, viewToDetach); 60885 } 60886 60887 if (removeIndex > 0) { 60888 lContainer[indexInContainer - 1][NEXT] = viewToDetach[NEXT]; 60889 } 60890 60891 const removedLView = removeFromArray(lContainer, CONTAINER_HEADER_OFFSET + removeIndex); 60892 removeViewFromContainer(viewToDetach[TVIEW], viewToDetach); // notify query that a view has been removed 60893 60894 const lQueries = removedLView[QUERIES]; 60895 60896 if (lQueries !== null) { 60897 lQueries.detachView(removedLView[TVIEW]); 60898 } 60899 60900 viewToDetach[PARENT] = null; 60901 viewToDetach[NEXT] = null; // Unsets the attached flag 60902 60903 viewToDetach[FLAGS] &= ~64 60904 /* LViewFlags.Attached */ 60905 ; 60906 } 60907 60908 return viewToDetach; 60909} 60910/** 60911 * A standalone function which destroys an LView, 60912 * conducting clean up (e.g. removing listeners, calling onDestroys). 60913 * 60914 * @param tView The `TView' of the `LView` to be destroyed 60915 * @param lView The view to be destroyed. 60916 */ 60917 60918 60919function destroyLView(tView, lView) { 60920 if (!(lView[FLAGS] & 128 60921 /* LViewFlags.Destroyed */ 60922 )) { 60923 const renderer = lView[RENDERER]; 60924 60925 if (renderer.destroyNode) { 60926 applyView(tView, lView, renderer, 3 60927 /* WalkTNodeTreeAction.Destroy */ 60928 , null, null); 60929 } 60930 60931 destroyViewTree(lView); 60932 } 60933} 60934/** 60935 * Calls onDestroys hooks for all directives and pipes in a given view and then removes all 60936 * listeners. Listeners are removed as the last step so events delivered in the onDestroys hooks 60937 * can be propagated to @Output listeners. 60938 * 60939 * @param tView `TView` for the `LView` to clean up. 60940 * @param lView The LView to clean up 60941 */ 60942 60943 60944function cleanUpView(tView, lView) { 60945 if (!(lView[FLAGS] & 128 60946 /* LViewFlags.Destroyed */ 60947 )) { 60948 // Usually the Attached flag is removed when the view is detached from its parent, however 60949 // if it's a root view, the flag won't be unset hence why we're also removing on destroy. 60950 lView[FLAGS] &= ~64 60951 /* LViewFlags.Attached */ 60952 ; // Mark the LView as destroyed *before* executing the onDestroy hooks. An onDestroy hook 60953 // runs arbitrary user code, which could include its own `viewRef.destroy()` (or similar). If 60954 // We don't flag the view as destroyed before the hooks, this could lead to an infinite loop. 60955 // This also aligns with the ViewEngine behavior. It also means that the onDestroy hook is 60956 // really more of an "afterDestroy" hook if you think about it. 60957 60958 lView[FLAGS] |= 128 60959 /* LViewFlags.Destroyed */ 60960 ; 60961 executeOnDestroys(tView, lView); 60962 processCleanups(tView, lView); // For component views only, the local renderer is destroyed at clean up time. 60963 60964 if (lView[TVIEW].type === 1 60965 /* TViewType.Component */ 60966 ) { 60967 ngDevMode && ngDevMode.rendererDestroy++; 60968 lView[RENDERER].destroy(); 60969 } 60970 60971 const declarationContainer = lView[DECLARATION_LCONTAINER]; // we are dealing with an embedded view that is still inserted into a container 60972 60973 if (declarationContainer !== null && isLContainer(lView[PARENT])) { 60974 // and this is a projected view 60975 if (declarationContainer !== lView[PARENT]) { 60976 detachMovedView(declarationContainer, lView); 60977 } // For embedded views still attached to a container: remove query result from this view. 60978 60979 60980 const lQueries = lView[QUERIES]; 60981 60982 if (lQueries !== null) { 60983 lQueries.detachView(tView); 60984 } 60985 } // Unregister the view once everything else has been cleaned up. 60986 60987 60988 unregisterLView(lView); 60989 } 60990} 60991/** Removes listeners and unsubscribes from output subscriptions */ 60992 60993 60994function processCleanups(tView, lView) { 60995 const tCleanup = tView.cleanup; 60996 const lCleanup = lView[CLEANUP]; // `LCleanup` contains both share information with `TCleanup` as well as instance specific 60997 // information appended at the end. We need to know where the end of the `TCleanup` information 60998 // is, and we track this with `lastLCleanupIndex`. 60999 61000 let lastLCleanupIndex = -1; 61001 61002 if (tCleanup !== null) { 61003 for (let i = 0; i < tCleanup.length - 1; i += 2) { 61004 if (typeof tCleanup[i] === 'string') { 61005 // This is a native DOM listener 61006 const idxOrTargetGetter = tCleanup[i + 1]; 61007 const target = typeof idxOrTargetGetter === 'function' ? idxOrTargetGetter(lView) : unwrapRNode(lView[idxOrTargetGetter]); 61008 const listener = lCleanup[lastLCleanupIndex = tCleanup[i + 2]]; 61009 const useCaptureOrSubIdx = tCleanup[i + 3]; 61010 61011 if (typeof useCaptureOrSubIdx === 'boolean') { 61012 // native DOM listener registered with Renderer3 61013 target.removeEventListener(tCleanup[i], listener, useCaptureOrSubIdx); 61014 } else { 61015 if (useCaptureOrSubIdx >= 0) { 61016 // unregister 61017 lCleanup[lastLCleanupIndex = useCaptureOrSubIdx](); 61018 } else { 61019 // Subscription 61020 lCleanup[lastLCleanupIndex = -useCaptureOrSubIdx].unsubscribe(); 61021 } 61022 } 61023 61024 i += 2; 61025 } else { 61026 // This is a cleanup function that is grouped with the index of its context 61027 const context = lCleanup[lastLCleanupIndex = tCleanup[i + 1]]; 61028 tCleanup[i].call(context); 61029 } 61030 } 61031 } 61032 61033 if (lCleanup !== null) { 61034 for (let i = lastLCleanupIndex + 1; i < lCleanup.length; i++) { 61035 const instanceCleanupFn = lCleanup[i]; 61036 ngDevMode && assertFunction(instanceCleanupFn, 'Expecting instance cleanup function.'); 61037 instanceCleanupFn(); 61038 } 61039 61040 lView[CLEANUP] = null; 61041 } 61042} 61043/** Calls onDestroy hooks for this view */ 61044 61045 61046function executeOnDestroys(tView, lView) { 61047 let destroyHooks; 61048 61049 if (tView != null && (destroyHooks = tView.destroyHooks) != null) { 61050 for (let i = 0; i < destroyHooks.length; i += 2) { 61051 const context = lView[destroyHooks[i]]; // Only call the destroy hook if the context has been requested. 61052 61053 if (!(context instanceof NodeInjectorFactory)) { 61054 const toCall = destroyHooks[i + 1]; 61055 61056 if (Array.isArray(toCall)) { 61057 for (let j = 0; j < toCall.length; j += 2) { 61058 const callContext = context[toCall[j]]; 61059 const hook = toCall[j + 1]; 61060 profiler(4 61061 /* ProfilerEvent.LifecycleHookStart */ 61062 , callContext, hook); 61063 61064 try { 61065 hook.call(callContext); 61066 } finally { 61067 profiler(5 61068 /* ProfilerEvent.LifecycleHookEnd */ 61069 , callContext, hook); 61070 } 61071 } 61072 } else { 61073 profiler(4 61074 /* ProfilerEvent.LifecycleHookStart */ 61075 , context, toCall); 61076 61077 try { 61078 toCall.call(context); 61079 } finally { 61080 profiler(5 61081 /* ProfilerEvent.LifecycleHookEnd */ 61082 , context, toCall); 61083 } 61084 } 61085 } 61086 } 61087 } 61088} 61089/** 61090 * Returns a native element if a node can be inserted into the given parent. 61091 * 61092 * There are two reasons why we may not be able to insert a element immediately. 61093 * - Projection: When creating a child content element of a component, we have to skip the 61094 * insertion because the content of a component will be projected. 61095 * `<component><content>delayed due to projection</content></component>` 61096 * - Parent container is disconnected: This can happen when we are inserting a view into 61097 * parent container, which itself is disconnected. For example the parent container is part 61098 * of a View which has not be inserted or is made for projection but has not been inserted 61099 * into destination. 61100 * 61101 * @param tView: Current `TView`. 61102 * @param tNode: `TNode` for which we wish to retrieve render parent. 61103 * @param lView: Current `LView`. 61104 */ 61105 61106 61107function getParentRElement(tView, tNode, lView) { 61108 return getClosestRElement(tView, tNode.parent, lView); 61109} 61110/** 61111 * Get closest `RElement` or `null` if it can't be found. 61112 * 61113 * If `TNode` is `TNodeType.Element` => return `RElement` at `LView[tNode.index]` location. 61114 * If `TNode` is `TNodeType.ElementContainer|IcuContain` => return the parent (recursively). 61115 * If `TNode` is `null` then return host `RElement`: 61116 * - return `null` if projection 61117 * - return `null` if parent container is disconnected (we have no parent.) 61118 * 61119 * @param tView: Current `TView`. 61120 * @param tNode: `TNode` for which we wish to retrieve `RElement` (or `null` if host element is 61121 * needed). 61122 * @param lView: Current `LView`. 61123 * @returns `null` if the `RElement` can't be determined at this time (no parent / projection) 61124 */ 61125 61126 61127function getClosestRElement(tView, tNode, lView) { 61128 let parentTNode = tNode; // Skip over element and ICU containers as those are represented by a comment node and 61129 // can't be used as a render parent. 61130 61131 while (parentTNode !== null && parentTNode.type & (8 61132 /* TNodeType.ElementContainer */ 61133 | 32 61134 /* TNodeType.Icu */ 61135 )) { 61136 tNode = parentTNode; 61137 parentTNode = tNode.parent; 61138 } // If the parent tNode is null, then we are inserting across views: either into an embedded view 61139 // or a component view. 61140 61141 61142 if (parentTNode === null) { 61143 // We are inserting a root element of the component view into the component host element and 61144 // it should always be eager. 61145 return lView[HOST]; 61146 } else { 61147 ngDevMode && assertTNodeType(parentTNode, 3 61148 /* TNodeType.AnyRNode */ 61149 | 4 61150 /* TNodeType.Container */ 61151 ); 61152 61153 if (parentTNode.flags & 2 61154 /* TNodeFlags.isComponentHost */ 61155 ) { 61156 ngDevMode && assertTNodeForLView(parentTNode, lView); 61157 const encapsulation = tView.data[parentTNode.directiveStart].encapsulation; // We've got a parent which is an element in the current view. We just need to verify if the 61158 // parent element is not a component. Component's content nodes are not inserted immediately 61159 // because they will be projected, and so doing insert at this point would be wasteful. 61160 // Since the projection would then move it to its final destination. Note that we can't 61161 // make this assumption when using the Shadow DOM, because the native projection placeholders 61162 // (<content> or <slot>) have to be in place as elements are being inserted. 61163 61164 if (encapsulation === ViewEncapsulation$1.None || encapsulation === ViewEncapsulation$1.Emulated) { 61165 return null; 61166 } 61167 } 61168 61169 return getNativeByTNode(parentTNode, lView); 61170 } 61171} 61172/** 61173 * Inserts a native node before another native node for a given parent. 61174 * This is a utility function that can be used when native nodes were determined. 61175 */ 61176 61177 61178function nativeInsertBefore(renderer, parent, child, beforeNode, isMove) { 61179 ngDevMode && ngDevMode.rendererInsertBefore++; 61180 renderer.insertBefore(parent, child, beforeNode, isMove); 61181} 61182 61183function nativeAppendChild(renderer, parent, child) { 61184 ngDevMode && ngDevMode.rendererAppendChild++; 61185 ngDevMode && assertDefined(parent, 'parent node must be defined'); 61186 renderer.appendChild(parent, child); 61187} 61188 61189function nativeAppendOrInsertBefore(renderer, parent, child, beforeNode, isMove) { 61190 if (beforeNode !== null) { 61191 nativeInsertBefore(renderer, parent, child, beforeNode, isMove); 61192 } else { 61193 nativeAppendChild(renderer, parent, child); 61194 } 61195} 61196/** Removes a node from the DOM given its native parent. */ 61197 61198 61199function nativeRemoveChild(renderer, parent, child, isHostElement) { 61200 renderer.removeChild(parent, child, isHostElement); 61201} 61202/** Checks if an element is a `<template>` node. */ 61203 61204 61205function isTemplateNode(node) { 61206 return node.tagName === 'TEMPLATE' && node.content !== undefined; 61207} 61208/** 61209 * Returns a native parent of a given native node. 61210 */ 61211 61212 61213function nativeParentNode(renderer, node) { 61214 return renderer.parentNode(node); 61215} 61216/** 61217 * Returns a native sibling of a given native node. 61218 */ 61219 61220 61221function nativeNextSibling(renderer, node) { 61222 return renderer.nextSibling(node); 61223} 61224/** 61225 * Find a node in front of which `currentTNode` should be inserted. 61226 * 61227 * This method determines the `RNode` in front of which we should insert the `currentRNode`. This 61228 * takes `TNode.insertBeforeIndex` into account if i18n code has been invoked. 61229 * 61230 * @param parentTNode parent `TNode` 61231 * @param currentTNode current `TNode` (The node which we would like to insert into the DOM) 61232 * @param lView current `LView` 61233 */ 61234 61235 61236function getInsertInFrontOfRNode(parentTNode, currentTNode, lView) { 61237 return _getInsertInFrontOfRNodeWithI18n(parentTNode, currentTNode, lView); 61238} 61239/** 61240 * Find a node in front of which `currentTNode` should be inserted. (Does not take i18n into 61241 * account) 61242 * 61243 * This method determines the `RNode` in front of which we should insert the `currentRNode`. This 61244 * does not take `TNode.insertBeforeIndex` into account. 61245 * 61246 * @param parentTNode parent `TNode` 61247 * @param currentTNode current `TNode` (The node which we would like to insert into the DOM) 61248 * @param lView current `LView` 61249 */ 61250 61251 61252function getInsertInFrontOfRNodeWithNoI18n(parentTNode, currentTNode, lView) { 61253 if (parentTNode.type & (8 61254 /* TNodeType.ElementContainer */ 61255 | 32 61256 /* TNodeType.Icu */ 61257 )) { 61258 return getNativeByTNode(parentTNode, lView); 61259 } 61260 61261 return null; 61262} 61263/** 61264 * Tree shakable boundary for `getInsertInFrontOfRNodeWithI18n` function. 61265 * 61266 * This function will only be set if i18n code runs. 61267 */ 61268 61269 61270let _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithNoI18n; 61271/** 61272 * Tree shakable boundary for `processI18nInsertBefore` function. 61273 * 61274 * This function will only be set if i18n code runs. 61275 */ 61276 61277let _processI18nInsertBefore; 61278 61279function setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore) { 61280 _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithI18n; 61281 _processI18nInsertBefore = processI18nInsertBefore; 61282} 61283/** 61284 * Appends the `child` native node (or a collection of nodes) to the `parent`. 61285 * 61286 * @param tView The `TView' to be appended 61287 * @param lView The current LView 61288 * @param childRNode The native child (or children) that should be appended 61289 * @param childTNode The TNode of the child element 61290 */ 61291 61292 61293function appendChild(tView, lView, childRNode, childTNode) { 61294 const parentRNode = getParentRElement(tView, childTNode, lView); 61295 const renderer = lView[RENDERER]; 61296 const parentTNode = childTNode.parent || lView[T_HOST]; 61297 const anchorNode = getInsertInFrontOfRNode(parentTNode, childTNode, lView); 61298 61299 if (parentRNode != null) { 61300 if (Array.isArray(childRNode)) { 61301 for (let i = 0; i < childRNode.length; i++) { 61302 nativeAppendOrInsertBefore(renderer, parentRNode, childRNode[i], anchorNode, false); 61303 } 61304 } else { 61305 nativeAppendOrInsertBefore(renderer, parentRNode, childRNode, anchorNode, false); 61306 } 61307 } 61308 61309 _processI18nInsertBefore !== undefined && _processI18nInsertBefore(renderer, childTNode, lView, childRNode, parentRNode); 61310} 61311/** 61312 * Returns the first native node for a given LView, starting from the provided TNode. 61313 * 61314 * Native nodes are returned in the order in which those appear in the native tree (DOM). 61315 */ 61316 61317 61318function getFirstNativeNode(lView, tNode) { 61319 if (tNode !== null) { 61320 ngDevMode && assertTNodeType(tNode, 3 61321 /* TNodeType.AnyRNode */ 61322 | 12 61323 /* TNodeType.AnyContainer */ 61324 | 32 61325 /* TNodeType.Icu */ 61326 | 16 61327 /* TNodeType.Projection */ 61328 ); 61329 const tNodeType = tNode.type; 61330 61331 if (tNodeType & 3 61332 /* TNodeType.AnyRNode */ 61333 ) { 61334 return getNativeByTNode(tNode, lView); 61335 } else if (tNodeType & 4 61336 /* TNodeType.Container */ 61337 ) { 61338 return getBeforeNodeForView(-1, lView[tNode.index]); 61339 } else if (tNodeType & 8 61340 /* TNodeType.ElementContainer */ 61341 ) { 61342 const elIcuContainerChild = tNode.child; 61343 61344 if (elIcuContainerChild !== null) { 61345 return getFirstNativeNode(lView, elIcuContainerChild); 61346 } else { 61347 const rNodeOrLContainer = lView[tNode.index]; 61348 61349 if (isLContainer(rNodeOrLContainer)) { 61350 return getBeforeNodeForView(-1, rNodeOrLContainer); 61351 } else { 61352 return unwrapRNode(rNodeOrLContainer); 61353 } 61354 } 61355 } else if (tNodeType & 32 61356 /* TNodeType.Icu */ 61357 ) { 61358 let nextRNode = icuContainerIterate(tNode, lView); 61359 let rNode = nextRNode(); // If the ICU container has no nodes, than we use the ICU anchor as the node. 61360 61361 return rNode || unwrapRNode(lView[tNode.index]); 61362 } else { 61363 const projectionNodes = getProjectionNodes(lView, tNode); 61364 61365 if (projectionNodes !== null) { 61366 if (Array.isArray(projectionNodes)) { 61367 return projectionNodes[0]; 61368 } 61369 61370 const parentView = getLViewParent(lView[DECLARATION_COMPONENT_VIEW]); 61371 ngDevMode && assertParentView(parentView); 61372 return getFirstNativeNode(parentView, projectionNodes); 61373 } else { 61374 return getFirstNativeNode(lView, tNode.next); 61375 } 61376 } 61377 } 61378 61379 return null; 61380} 61381 61382function getProjectionNodes(lView, tNode) { 61383 if (tNode !== null) { 61384 const componentView = lView[DECLARATION_COMPONENT_VIEW]; 61385 const componentHost = componentView[T_HOST]; 61386 const slotIdx = tNode.projection; 61387 ngDevMode && assertProjectionSlots(lView); 61388 return componentHost.projection[slotIdx]; 61389 } 61390 61391 return null; 61392} 61393 61394function getBeforeNodeForView(viewIndexInContainer, lContainer) { 61395 const nextViewIndex = CONTAINER_HEADER_OFFSET + viewIndexInContainer + 1; 61396 61397 if (nextViewIndex < lContainer.length) { 61398 const lView = lContainer[nextViewIndex]; 61399 const firstTNodeOfView = lView[TVIEW].firstChild; 61400 61401 if (firstTNodeOfView !== null) { 61402 return getFirstNativeNode(lView, firstTNodeOfView); 61403 } 61404 } 61405 61406 return lContainer[NATIVE]; 61407} 61408/** 61409 * Removes a native node itself using a given renderer. To remove the node we are looking up its 61410 * parent from the native tree as not all platforms / browsers support the equivalent of 61411 * node.remove(). 61412 * 61413 * @param renderer A renderer to be used 61414 * @param rNode The native node that should be removed 61415 * @param isHostElement A flag indicating if a node to be removed is a host of a component. 61416 */ 61417 61418 61419function nativeRemoveNode(renderer, rNode, isHostElement) { 61420 ngDevMode && ngDevMode.rendererRemoveNode++; 61421 const nativeParent = nativeParentNode(renderer, rNode); 61422 61423 if (nativeParent) { 61424 nativeRemoveChild(renderer, nativeParent, rNode, isHostElement); 61425 } 61426} 61427/** 61428 * Performs the operation of `action` on the node. Typically this involves inserting or removing 61429 * nodes on the LView or projection boundary. 61430 */ 61431 61432 61433function applyNodes(renderer, action, tNode, lView, parentRElement, beforeNode, isProjection) { 61434 while (tNode != null) { 61435 ngDevMode && assertTNodeForLView(tNode, lView); 61436 ngDevMode && assertTNodeType(tNode, 3 61437 /* TNodeType.AnyRNode */ 61438 | 12 61439 /* TNodeType.AnyContainer */ 61440 | 16 61441 /* TNodeType.Projection */ 61442 | 32 61443 /* TNodeType.Icu */ 61444 ); 61445 const rawSlotValue = lView[tNode.index]; 61446 const tNodeType = tNode.type; 61447 61448 if (isProjection) { 61449 if (action === 0 61450 /* WalkTNodeTreeAction.Create */ 61451 ) { 61452 rawSlotValue && attachPatchData(unwrapRNode(rawSlotValue), lView); 61453 tNode.flags |= 4 61454 /* TNodeFlags.isProjected */ 61455 ; 61456 } 61457 } 61458 61459 if ((tNode.flags & 64 61460 /* TNodeFlags.isDetached */ 61461 ) !== 64 61462 /* TNodeFlags.isDetached */ 61463 ) { 61464 if (tNodeType & 8 61465 /* TNodeType.ElementContainer */ 61466 ) { 61467 applyNodes(renderer, action, tNode.child, lView, parentRElement, beforeNode, false); 61468 applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode); 61469 } else if (tNodeType & 32 61470 /* TNodeType.Icu */ 61471 ) { 61472 const nextRNode = icuContainerIterate(tNode, lView); 61473 let rNode; 61474 61475 while (rNode = nextRNode()) { 61476 applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode); 61477 } 61478 61479 applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode); 61480 } else if (tNodeType & 16 61481 /* TNodeType.Projection */ 61482 ) { 61483 applyProjectionRecursive(renderer, action, lView, tNode, parentRElement, beforeNode); 61484 } else { 61485 ngDevMode && assertTNodeType(tNode, 3 61486 /* TNodeType.AnyRNode */ 61487 | 4 61488 /* TNodeType.Container */ 61489 ); 61490 applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode); 61491 } 61492 } 61493 61494 tNode = isProjection ? tNode.projectionNext : tNode.next; 61495 } 61496} 61497 61498function applyView(tView, lView, renderer, action, parentRElement, beforeNode) { 61499 applyNodes(renderer, action, tView.firstChild, lView, parentRElement, beforeNode, false); 61500} 61501/** 61502 * `applyProjection` performs operation on the projection. 61503 * 61504 * Inserting a projection requires us to locate the projected nodes from the parent component. The 61505 * complication is that those nodes themselves could be re-projected from their parent component. 61506 * 61507 * @param tView The `TView` of `LView` which needs to be inserted, detached, destroyed 61508 * @param lView The `LView` which needs to be inserted, detached, destroyed. 61509 * @param tProjectionNode node to project 61510 */ 61511 61512 61513function applyProjection(tView, lView, tProjectionNode) { 61514 const renderer = lView[RENDERER]; 61515 const parentRNode = getParentRElement(tView, tProjectionNode, lView); 61516 const parentTNode = tProjectionNode.parent || lView[T_HOST]; 61517 let beforeNode = getInsertInFrontOfRNode(parentTNode, tProjectionNode, lView); 61518 applyProjectionRecursive(renderer, 0 61519 /* WalkTNodeTreeAction.Create */ 61520 , lView, tProjectionNode, parentRNode, beforeNode); 61521} 61522/** 61523 * `applyProjectionRecursive` performs operation on the projection specified by `action` (insert, 61524 * detach, destroy) 61525 * 61526 * Inserting a projection requires us to locate the projected nodes from the parent component. The 61527 * complication is that those nodes themselves could be re-projected from their parent component. 61528 * 61529 * @param renderer Render to use 61530 * @param action action to perform (insert, detach, destroy) 61531 * @param lView The LView which needs to be inserted, detached, destroyed. 61532 * @param tProjectionNode node to project 61533 * @param parentRElement parent DOM element for insertion/removal. 61534 * @param beforeNode Before which node the insertions should happen. 61535 */ 61536 61537 61538function applyProjectionRecursive(renderer, action, lView, tProjectionNode, parentRElement, beforeNode) { 61539 const componentLView = lView[DECLARATION_COMPONENT_VIEW]; 61540 const componentNode = componentLView[T_HOST]; 61541 ngDevMode && assertEqual(typeof tProjectionNode.projection, 'number', 'expecting projection index'); 61542 const nodeToProjectOrRNodes = componentNode.projection[tProjectionNode.projection]; 61543 61544 if (Array.isArray(nodeToProjectOrRNodes)) { 61545 // This should not exist, it is a bit of a hack. When we bootstrap a top level node and we 61546 // need to support passing projectable nodes, so we cheat and put them in the TNode 61547 // of the Host TView. (Yes we put instance info at the T Level). We can get away with it 61548 // because we know that that TView is not shared and therefore it will not be a problem. 61549 // This should be refactored and cleaned up. 61550 for (let i = 0; i < nodeToProjectOrRNodes.length; i++) { 61551 const rNode = nodeToProjectOrRNodes[i]; 61552 applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode); 61553 } 61554 } else { 61555 let nodeToProject = nodeToProjectOrRNodes; 61556 const projectedComponentLView = componentLView[PARENT]; 61557 applyNodes(renderer, action, nodeToProject, projectedComponentLView, parentRElement, beforeNode, true); 61558 } 61559} 61560/** 61561 * `applyContainer` performs an operation on the container and its views as specified by 61562 * `action` (insert, detach, destroy) 61563 * 61564 * Inserting a Container is complicated by the fact that the container may have Views which 61565 * themselves have containers or projections. 61566 * 61567 * @param renderer Renderer to use 61568 * @param action action to perform (insert, detach, destroy) 61569 * @param lContainer The LContainer which needs to be inserted, detached, destroyed. 61570 * @param parentRElement parent DOM element for insertion/removal. 61571 * @param beforeNode Before which node the insertions should happen. 61572 */ 61573 61574 61575function applyContainer(renderer, action, lContainer, parentRElement, beforeNode) { 61576 ngDevMode && assertLContainer(lContainer); 61577 const anchor = lContainer[NATIVE]; // LContainer has its own before node. 61578 61579 const native = unwrapRNode(lContainer); // An LContainer can be created dynamically on any node by injecting ViewContainerRef. 61580 // Asking for a ViewContainerRef on an element will result in a creation of a separate anchor 61581 // node (comment in the DOM) that will be different from the LContainer's host node. In this 61582 // particular case we need to execute action on 2 nodes: 61583 // - container's host node (this is done in the executeActionOnElementOrContainer) 61584 // - container's host node (this is done here) 61585 61586 if (anchor !== native) { 61587 // This is very strange to me (Misko). I would expect that the native is same as anchor. I 61588 // don't see a reason why they should be different, but they are. 61589 // 61590 // If they are we need to process the second anchor as well. 61591 applyToElementOrContainer(action, renderer, parentRElement, anchor, beforeNode); 61592 } 61593 61594 for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) { 61595 const lView = lContainer[i]; 61596 applyView(lView[TVIEW], lView, renderer, action, parentRElement, anchor); 61597 } 61598} 61599/** 61600 * Writes class/style to element. 61601 * 61602 * @param renderer Renderer to use. 61603 * @param isClassBased `true` if it should be written to `class` (`false` to write to `style`) 61604 * @param rNode The Node to write to. 61605 * @param prop Property to write to. This would be the class/style name. 61606 * @param value Value to write. If `null`/`undefined`/`false` this is considered a remove (set/add 61607 * otherwise). 61608 */ 61609 61610 61611function applyStyling(renderer, isClassBased, rNode, prop, value) { 61612 if (isClassBased) { 61613 // We actually want JS true/false here because any truthy value should add the class 61614 if (!value) { 61615 ngDevMode && ngDevMode.rendererRemoveClass++; 61616 renderer.removeClass(rNode, prop); 61617 } else { 61618 ngDevMode && ngDevMode.rendererAddClass++; 61619 renderer.addClass(rNode, prop); 61620 } 61621 } else { 61622 let flags = prop.indexOf('-') === -1 ? undefined : RendererStyleFlags2.DashCase; 61623 61624 if (value == null 61625 /** || value === undefined */ 61626 ) { 61627 ngDevMode && ngDevMode.rendererRemoveStyle++; 61628 renderer.removeStyle(rNode, prop, flags); 61629 } else { 61630 // A value is important if it ends with `!important`. The style 61631 // parser strips any semicolons at the end of the value. 61632 const isImportant = typeof value === 'string' ? value.endsWith('!important') : false; 61633 61634 if (isImportant) { 61635 // !important has to be stripped from the value for it to be valid. 61636 value = value.slice(0, -10); 61637 flags |= RendererStyleFlags2.Important; 61638 } 61639 61640 ngDevMode && ngDevMode.rendererSetStyle++; 61641 renderer.setStyle(rNode, prop, value, flags); 61642 } 61643 } 61644} 61645/** 61646 * Write `cssText` to `RElement`. 61647 * 61648 * This function does direct write without any reconciliation. Used for writing initial values, so 61649 * that static styling values do not pull in the style parser. 61650 * 61651 * @param renderer Renderer to use 61652 * @param element The element which needs to be updated. 61653 * @param newValue The new class list to write. 61654 */ 61655 61656 61657function writeDirectStyle(renderer, element, newValue) { 61658 ngDevMode && assertString(newValue, '\'newValue\' should be a string'); 61659 renderer.setAttribute(element, 'style', newValue); 61660 ngDevMode && ngDevMode.rendererSetStyle++; 61661} 61662/** 61663 * Write `className` to `RElement`. 61664 * 61665 * This function does direct write without any reconciliation. Used for writing initial values, so 61666 * that static styling values do not pull in the style parser. 61667 * 61668 * @param renderer Renderer to use 61669 * @param element The element which needs to be updated. 61670 * @param newValue The new class list to write. 61671 */ 61672 61673 61674function writeDirectClass(renderer, element, newValue) { 61675 ngDevMode && assertString(newValue, '\'newValue\' should be a string'); 61676 61677 if (newValue === '') { 61678 // There are tests in `google3` which expect `element.getAttribute('class')` to be `null`. 61679 renderer.removeAttribute(element, 'class'); 61680 } else { 61681 renderer.setAttribute(element, 'class', newValue); 61682 } 61683 61684 ngDevMode && ngDevMode.rendererSetClassName++; 61685} 61686/** 61687 * @license 61688 * Copyright Google LLC All Rights Reserved. 61689 * 61690 * Use of this source code is governed by an MIT-style license that can be 61691 * found in the LICENSE file at https://angular.io/license 61692 */ 61693 61694/** 61695 * Returns an index of `classToSearch` in `className` taking token boundaries into account. 61696 * 61697 * `classIndexOf('AB A', 'A', 0)` will be 3 (not 0 since `AB!==A`) 61698 * 61699 * @param className A string containing classes (whitespace separated) 61700 * @param classToSearch A class name to locate 61701 * @param startingIndex Starting location of search 61702 * @returns an index of the located class (or -1 if not found) 61703 */ 61704 61705 61706function classIndexOf(className, classToSearch, startingIndex) { 61707 ngDevMode && assertNotEqual(classToSearch, '', 'can not look for "" string.'); 61708 let end = className.length; 61709 61710 while (true) { 61711 const foundIndex = className.indexOf(classToSearch, startingIndex); 61712 if (foundIndex === -1) return foundIndex; 61713 61714 if (foundIndex === 0 || className.charCodeAt(foundIndex - 1) <= 32 61715 /* CharCode.SPACE */ 61716 ) { 61717 // Ensure that it has leading whitespace 61718 const length = classToSearch.length; 61719 61720 if (foundIndex + length === end || className.charCodeAt(foundIndex + length) <= 32 61721 /* CharCode.SPACE */ 61722 ) { 61723 // Ensure that it has trailing whitespace 61724 return foundIndex; 61725 } 61726 } // False positive, keep searching from where we left off. 61727 61728 61729 startingIndex = foundIndex + 1; 61730 } 61731} 61732/** 61733 * @license 61734 * Copyright Google LLC All Rights Reserved. 61735 * 61736 * Use of this source code is governed by an MIT-style license that can be 61737 * found in the LICENSE file at https://angular.io/license 61738 */ 61739 61740 61741const unusedValueToPlacateAjd$1 = unusedValueExportToPlacateAjd$5 + unusedValueExportToPlacateAjd$4; 61742const NG_TEMPLATE_SELECTOR = 'ng-template'; 61743/** 61744 * Search the `TAttributes` to see if it contains `cssClassToMatch` (case insensitive) 61745 * 61746 * @param attrs `TAttributes` to search through. 61747 * @param cssClassToMatch class to match (lowercase) 61748 * @param isProjectionMode Whether or not class matching should look into the attribute `class` in 61749 * addition to the `AttributeMarker.Classes`. 61750 */ 61751 61752function isCssClassMatching(attrs, cssClassToMatch, isProjectionMode) { 61753 // TODO(misko): The fact that this function needs to know about `isProjectionMode` seems suspect. 61754 // It is strange to me that sometimes the class information comes in form of `class` attribute
61755 // and sometimes in form of `AttributeMarker.Classes`. Some investigation is needed to determine 61756 // if that is the right behavior. 61757 ngDevMode && assertEqual(cssClassToMatch, cssClassToMatch.toLowerCase(), 'Class name expected to be lowercase.'); 61758 let i = 0; 61759 61760 while (i < attrs.length) { 61761 let item = attrs[i++]; 61762 61763 if (isProjectionMode && item === 'class') { 61764 item = attrs[i]; 61765 61766 if (classIndexOf(item.toLowerCase(), cssClassToMatch, 0) !== -1) { 61767 return true; 61768 } 61769 } else if (item === 1 61770 /* AttributeMarker.Classes */ 61771 ) { 61772 // We found the classes section. Start searching for the class. 61773 while (i < attrs.length && typeof (item = attrs[i++]) == 'string') { 61774 // while we have strings 61775 if (item.toLowerCase() === cssClassToMatch) return true; 61776 } 61777 61778 return false; 61779 } 61780 } 61781 61782 return false; 61783} 61784/** 61785 * Checks whether the `tNode` represents an inline template (e.g. `*ngFor`). 61786 * 61787 * @param tNode current TNode 61788 */ 61789 61790 61791function isInlineTemplate(tNode) { 61792 return tNode.type === 4 61793 /* TNodeType.Container */ 61794 && tNode.value !== NG_TEMPLATE_SELECTOR; 61795} 61796/** 61797 * Function that checks whether a given tNode matches tag-based selector and has a valid type. 61798 * 61799 * Matching can be performed in 2 modes: projection mode (when we project nodes) and regular 61800 * directive matching mode: 61801 * - in the "directive matching" mode we do _not_ take TContainer's tagName into account if it is 61802 * different from NG_TEMPLATE_SELECTOR (value different from NG_TEMPLATE_SELECTOR indicates that a 61803 * tag name was extracted from * syntax so we would match the same directive twice); 61804 * - in the "projection" mode, we use a tag name potentially extracted from the * syntax processing 61805 * (applicable to TNodeType.Container only). 61806 */ 61807 61808 61809function hasTagAndTypeMatch(tNode, currentSelector, isProjectionMode) { 61810 const tagNameToCompare = tNode.type === 4 61811 /* TNodeType.Container */ 61812 && !isProjectionMode ? NG_TEMPLATE_SELECTOR : tNode.value; 61813 return currentSelector === tagNameToCompare; 61814} 61815/** 61816 * A utility function to match an Ivy node static data against a simple CSS selector 61817 * 61818 * @param node static data of the node to match 61819 * @param selector The selector to try matching against the node. 61820 * @param isProjectionMode if `true` we are matching for content projection, otherwise we are doing 61821 * directive matching. 61822 * @returns true if node matches the selector. 61823 */ 61824 61825 61826function isNodeMatchingSelector(tNode, selector, isProjectionMode) { 61827 ngDevMode && assertDefined(selector[0], 'Selector should have a tag name'); 61828 let mode = 4 61829 /* SelectorFlags.ELEMENT */ 61830 ; 61831 const nodeAttrs = tNode.attrs || []; // Find the index of first attribute that has no value, only a name. 61832 61833 const nameOnlyMarkerIdx = getNameOnlyMarkerIndex(nodeAttrs); // When processing ":not" selectors, we skip to the next ":not" if the 61834 // current one doesn't match 61835 61836 let skipToNextSelector = false; 61837 61838 for (let i = 0; i < selector.length; i++) { 61839 const current = selector[i]; 61840 61841 if (typeof current === 'number') { 61842 // If we finish processing a :not selector and it hasn't failed, return false 61843 if (!skipToNextSelector && !isPositive(mode) && !isPositive(current)) { 61844 return false; 61845 } // If we are skipping to the next :not() and this mode flag is positive, 61846 // it's a part of the current :not() selector, and we should keep skipping 61847 61848 61849 if (skipToNextSelector && isPositive(current)) continue; 61850 skipToNextSelector = false; 61851 mode = current | mode & 1 61852 /* SelectorFlags.NOT */ 61853 ; 61854 continue; 61855 } 61856 61857 if (skipToNextSelector) continue; 61858 61859 if (mode & 4 61860 /* SelectorFlags.ELEMENT */ 61861 ) { 61862 mode = 2 61863 /* SelectorFlags.ATTRIBUTE */ 61864 | mode & 1 61865 /* SelectorFlags.NOT */ 61866 ; 61867 61868 if (current !== '' && !hasTagAndTypeMatch(tNode, current, isProjectionMode) || current === '' && selector.length === 1) { 61869 if (isPositive(mode)) return false; 61870 skipToNextSelector = true; 61871 } 61872 } else { 61873 const selectorAttrValue = mode & 8 61874 /* SelectorFlags.CLASS */ 61875 ? current : selector[++i]; // special case for matching against classes when a tNode has been instantiated with 61876 // class and style values as separate attribute values (e.g. ['title', CLASS, 'foo']) 61877 61878 if (mode & 8 61879 /* SelectorFlags.CLASS */ 61880 && tNode.attrs !== null) { 61881 if (!isCssClassMatching(tNode.attrs, selectorAttrValue, isProjectionMode)) { 61882 if (isPositive(mode)) return false;
vendor: 9,500 bytes, lines 61883-62180
61883 skipToNextSelector = true; 61884 } 61885 61886 continue; 61887 } 61888 61889 const attrName = mode & 8 61890 /* SelectorFlags.CLASS */ 61891 ? 'class' : current; 61892 const attrIndexInNode = findAttrIndexInNode(attrName, nodeAttrs, isInlineTemplate(tNode), isProjectionMode); 61893 61894 if (attrIndexInNode === -1) { 61895 if (isPositive(mode)) return false; 61896 skipToNextSelector = true; 61897 continue; 61898 } 61899 61900 if (selectorAttrValue !== '') { 61901 let nodeAttrValue; 61902 61903 if (attrIndexInNode > nameOnlyMarkerIdx) { 61904 nodeAttrValue = ''; 61905 } else { 61906 ngDevMode && assertNotEqual(nodeAttrs[attrIndexInNode], 0 61907 /* AttributeMarker.NamespaceURI */ 61908 , 'We do not match directives on namespaced attributes'); // we lowercase the attribute value to be able to match 61909 // selectors without case-sensitivity 61910 // (selectors are already in lowercase when generated) 61911 61912 nodeAttrValue = nodeAttrs[attrIndexInNode + 1].toLowerCase(); 61913 } 61914 61915 const compareAgainstClassName = mode & 8 61916 /* SelectorFlags.CLASS */ 61917 ? nodeAttrValue : null; 61918 61919 if (compareAgainstClassName && classIndexOf(compareAgainstClassName, selectorAttrValue, 0) !== -1 || mode & 2 61920 /* SelectorFlags.ATTRIBUTE */ 61921 && selectorAttrValue !== nodeAttrValue) { 61922 if (isPositive(mode)) return false; 61923 skipToNextSelector = true; 61924 } 61925 } 61926 } 61927 } 61928 61929 return isPositive(mode) || skipToNextSelector; 61930} 61931 61932function isPositive(mode) { 61933 return (mode & 1 61934 /* SelectorFlags.NOT */ 61935 ) === 0; 61936} 61937/** 61938 * Examines the attribute's definition array for a node to find the index of the 61939 * attribute that matches the given `name`. 61940 * 61941 * NOTE: This will not match namespaced attributes. 61942 * 61943 * Attribute matching depends upon `isInlineTemplate` and `isProjectionMode`. 61944 * The following table summarizes which types of attributes we attempt to match: 61945 * 61946 * =========================================================================================================== 61947 * Modes | Normal Attributes | Bindings Attributes | Template Attributes | I18n 61948 * Attributes 61949 * =========================================================================================================== 61950 * Inline + Projection | YES | YES | NO | YES 61951 * ----------------------------------------------------------------------------------------------------------- 61952 * Inline + Directive | NO | NO | YES | NO 61953 * ----------------------------------------------------------------------------------------------------------- 61954 * Non-inline + Projection | YES | YES | NO | YES 61955 * ----------------------------------------------------------------------------------------------------------- 61956 * Non-inline + Directive | YES | YES | NO | YES 61957 * =========================================================================================================== 61958 * 61959 * @param name the name of the attribute to find 61960 * @param attrs the attribute array to examine 61961 * @param isInlineTemplate true if the node being matched is an inline template (e.g. `*ngFor`) 61962 * rather than a manually expanded template node (e.g `<ng-template>`). 61963 * @param isProjectionMode true if we are matching against content projection otherwise we are 61964 * matching against directives. 61965 */ 61966 61967 61968function findAttrIndexInNode(name, attrs, isInlineTemplate, isProjectionMode) { 61969 if (attrs === null) return -1; 61970 let i = 0; 61971 61972 if (isProjectionMode || !isInlineTemplate) { 61973 let bindingsMode = false; 61974 61975 while (i < attrs.length) { 61976 const maybeAttrName = attrs[i]; 61977 61978 if (maybeAttrName === name) { 61979 return i; 61980 } else if (maybeAttrName === 3 61981 /* AttributeMarker.Bindings */ 61982 || maybeAttrName === 6 61983 /* AttributeMarker.I18n */ 61984 ) { 61985 bindingsMode = true; 61986 } else if (maybeAttrName === 1 61987 /* AttributeMarker.Classes */ 61988 || maybeAttrName === 2 61989 /* AttributeMarker.Styles */ 61990 ) { 61991 let value = attrs[++i]; // We should skip classes here because we have a separate mechanism for 61992 // matching classes in projection mode. 61993 61994 while (typeof value === 'string') { 61995 value = attrs[++i]; 61996 } 61997 61998 continue; 61999 } else if (maybeAttrName === 4 62000 /* AttributeMarker.Template */ 62001 ) { 62002 // We do not care about Template attributes in this scenario. 62003 break; 62004 } else if (maybeAttrName === 0 62005 /* AttributeMarker.NamespaceURI */ 62006 ) { 62007 // Skip the whole namespaced attribute and value. This is by design. 62008 i += 4; 62009 continue; 62010 } // In binding mode there are only names, rather than name-value pairs. 62011 62012 62013 i += bindingsMode ? 1 : 2; 62014 } // We did not match the attribute 62015 62016 62017 return -1; 62018 } else { 62019 return matchTemplateAttribute(attrs, name); 62020 } 62021} 62022 62023function isNodeMatchingSelectorList(tNode, selector, isProjectionMode = false) { 62024 for (let i = 0; i < selector.length; i++) { 62025 if (isNodeMatchingSelector(tNode, selector[i], isProjectionMode)) { 62026 return true; 62027 } 62028 } 62029 62030 return false; 62031} 62032 62033function getProjectAsAttrValue(tNode) { 62034 const nodeAttrs = tNode.attrs; 62035 62036 if (nodeAttrs != null) { 62037 const ngProjectAsAttrIdx = nodeAttrs.indexOf(5 62038 /* AttributeMarker.ProjectAs */ 62039 ); // only check for ngProjectAs in attribute names, don't accidentally match attribute's value 62040 // (attribute names are stored at even indexes) 62041 62042 if ((ngProjectAsAttrIdx & 1) === 0) { 62043 return nodeAttrs[ngProjectAsAttrIdx + 1]; 62044 } 62045 } 62046 62047 return null; 62048} 62049 62050function getNameOnlyMarkerIndex(nodeAttrs) { 62051 for (let i = 0; i < nodeAttrs.length; i++) { 62052 const nodeAttr = nodeAttrs[i]; 62053 62054 if (isNameOnlyAttributeMarker(nodeAttr)) { 62055 return i; 62056 } 62057 } 62058 62059 return nodeAttrs.length; 62060} 62061 62062function matchTemplateAttribute(attrs, name) { 62063 let i = attrs.indexOf(4 62064 /* AttributeMarker.Template */ 62065 ); 62066 62067 if (i > -1) { 62068 i++; 62069 62070 while (i < attrs.length) { 62071 const attr = attrs[i]; // Return in case we checked all template attrs and are switching to the next section in the 62072 // attrs array (that starts with a number that represents an attribute marker). 62073 62074 if (typeof attr === 'number') return -1; 62075 if (attr === name) return i; 62076 i++; 62077 } 62078 } 62079 62080 return -1; 62081} 62082/** 62083 * Checks whether a selector is inside a CssSelectorList 62084 * @param selector Selector to be checked. 62085 * @param list List in which to look for the selector. 62086 */ 62087 62088 62089function isSelectorInSelectorList(selector, list) { 62090 selectorListLoop: for (let i = 0; i < list.length; i++) { 62091 const currentSelectorInList = list[i]; 62092 62093 if (selector.length !== currentSelectorInList.length) { 62094 continue; 62095 } 62096 62097 for (let j = 0; j < selector.length; j++) { 62098 if (selector[j] !== currentSelectorInList[j]) { 62099 continue selectorListLoop; 62100 } 62101 } 62102 62103 return true; 62104 } 62105 62106 return false; 62107} 62108 62109function maybeWrapInNotSelector(isNegativeMode, chunk) { 62110 return isNegativeMode ? ':not(' + chunk.trim() + ')' : chunk; 62111} 62112 62113function stringifyCSSSelector(selector) { 62114 let result = selector[0]; 62115 let i = 1; 62116 let mode = 2 62117 /* SelectorFlags.ATTRIBUTE */ 62118 ; 62119 let currentChunk = ''; 62120 let isNegativeMode = false; 62121 62122 while (i < selector.length) { 62123 let valueOrMarker = selector[i]; 62124 62125 if (typeof valueOrMarker === 'string') { 62126 if (mode & 2 62127 /* SelectorFlags.ATTRIBUTE */ 62128 ) { 62129 const attrValue = selector[++i]; 62130 currentChunk += '[' + valueOrMarker + (attrValue.length > 0 ? '="' + attrValue + '"' : '') + ']'; 62131 } else if (mode & 8 62132 /* SelectorFlags.CLASS */ 62133 ) { 62134 currentChunk += '.' + valueOrMarker; 62135 } else if (mode & 4 62136 /* SelectorFlags.ELEMENT */ 62137 ) { 62138 currentChunk += ' ' + valueOrMarker; 62139 } 62140 } else { 62141 // 62142 // Append current chunk to the final result in case we come across SelectorFlag, which 62143 // indicates that the previous section of a selector is over. We need to accumulate content 62144 // between flags to make sure we wrap the chunk later in :not() selector if needed, e.g. 62145 // ``` 62146 // ['', Flags.CLASS, '.classA', Flags.CLASS | Flags.NOT, '.classB', '.classC'] 62147 // ``` 62148 // should be transformed to `.classA :not(.classB .classC)`. 62149 // 62150 // Note: for negative selector part, we accumulate content between flags until we find the 62151 // next negative flag. This is needed to support a case where `:not()` rule contains more than 62152 // one chunk, e.g. the following selector: 62153 // ``` 62154 // ['', Flags.ELEMENT | Flags.NOT, 'p', Flags.CLASS, 'foo', Flags.CLASS | Flags.NOT, 'bar'] 62155 // ``` 62156 // should be stringified to `:not(p.foo) :not(.bar)` 62157 // 62158 if (currentChunk !== '' && !isPositive(valueOrMarker)) { 62159 result += maybeWrapInNotSelector(isNegativeMode, currentChunk); 62160 currentChunk = ''; 62161 } 62162 62163 mode = valueOrMarker; // According to CssSelector spec, once we come across `SelectorFlags.NOT` flag, the negative 62164 // mode is maintained for remaining chunks of a selector. 62165 62166 isNegativeMode = isNegativeMode || !isPositive(mode); 62167 } 62168 62169 i++; 62170 } 62171 62172 if (currentChunk !== '') { 62173 result += maybeWrapInNotSelector(isNegativeMode, currentChunk); 62174 } 62175 62176 return result; 62177} 62178/** 62179 * Generates string representation of CSS selector in parsed form. 62180 *
62181 * ComponentDef and DirectiveDef are generated with the selector in parsed form to avoid doing 62182 * additional parsing at runtime (for example, for directive matching). However in some cases (for 62183 * example, while bootstrapping a component), a string version of the selector is required to query 62184 * for the host element on the page. This function takes the parsed form of a selector and returns 62185 * its string representation. 62186 * 62187 * @param selectorList selector in parsed form 62188 * @returns string representation of a given selector 62189 */ 62190 62191 62192function stringifyCSSSelectorList(selectorList) { 62193 return selectorList.map(stringifyCSSSelector).join(','); 62194} 62195/** 62196 * Extracts attributes and classes information from a given CSS selector. 62197 * 62198 * This function is used while creating a component dynamically. In this case, the host element 62199 * (that is created dynamically) should contain attributes and classes specified in component's CSS 62200 * selector. 62201 * 62202 * @param selector CSS selector in parsed form (in a form of array) 62203 * @returns object with `attrs` and `classes` fields that contain extracted information 62204 */ 62205 62206 62207function extractAttrsAndClassesFromSelector(selector) { 62208 const attrs = []; 62209 const classes = []; 62210 let i = 1; 62211 let mode = 2 62212 /* SelectorFlags.ATTRIBUTE */ 62213 ; 62214 62215 while (i < selector.length) { 62216 let valueOrMarker = selector[i]; 62217 62218 if (typeof valueOrMarker === 'string') { 62219 if (mode === 2 62220 /* SelectorFlags.ATTRIBUTE */ 62221 ) { 62222 if (valueOrMarker !== '') { 62223 attrs.push(valueOrMarker, selector[++i]); 62224 } 62225 } else if (mode === 8 62226 /* SelectorFlags.CLASS */ 62227 ) { 62228 classes.push(valueOrMarker); 62229 } 62230 } else { 62231 // According to CssSelector spec, once we come across `SelectorFlags.NOT` flag, the negative 62232 // mode is maintained for remaining chunks of a selector. Since attributes and classes are 62233 // extracted only for "positive" part of the selector, we can stop here. 62234 if (!isPositive(mode)) break; 62235 mode = valueOrMarker; 62236 } 62237 62238 i++; 62239 } 62240 62241 return { 62242 attrs, 62243 classes 62244 }; 62245} 62246/** 62247 * @license 62248 * Copyright Google LLC All Rights Reserved. 62249 * 62250 * Use of this source code is governed by an MIT-style license that can be 62251 * found in the LICENSE file at https://angular.io/license 62252 */ 62253 62254/** A special value which designates that a value has not changed. */ 62255 62256 62257const NO_CHANGE = typeof ngDevMode === 'undefined' || ngDevMode ? { 62258 __brand__: 'NO_CHANGE' 62259} : {}; 62260/** 62261 * @license 62262 * Copyright Google LLC All Rights Reserved. 62263 * 62264 * Use of this source code is governed by an MIT-style license that can be 62265 * found in the LICENSE file at https://angular.io/license 62266 */ 62267 62268/** 62269 * Advances to an element for later binding instructions. 62270 * 62271 * Used in conjunction with instructions like {@link property} to act on elements with specified 62272 * indices, for example those created with {@link element} or {@link elementStart}. 62273 * 62274 * ```ts 62275 * (rf: RenderFlags, ctx: any) => { 62276 * if (rf & 1) { 62277 * text(0, 'Hello'); 62278 * text(1, 'Goodbye') 62279 * element(2, 'div'); 62280 * } 62281 * if (rf & 2) { 62282 * advance(2); // Advance twice to the <div>. 62283 * property('title', 'test'); 62284 * } 62285 * } 62286 * ``` 62287 * @param delta Number of elements to advance forwards by. 62288 * 62289 * @codeGenApi 62290 */ 62291 62292function ɵɵadvance(delta) { 62293 ngDevMode && assertGreaterThan(delta, 0, 'Can only advance forward'); 62294 selectIndexInternal(getTView(), getLView(), getSelectedIndex() + delta, !!ngDevMode && isInCheckNoChangesMode()); 62295} 62296 62297function selectIndexInternal(tView, lView, index, checkNoChangesMode) { 62298 ngDevMode && assertIndexInDeclRange(lView, index); // Flush the initial hooks for elements in the view that have been added up to this point. 62299 // PERF WARNING: do NOT extract this to a separate function without running benchmarks 62300 62301 if (!checkNoChangesMode) { 62302 const hooksInitPhaseCompleted = (lView[FLAGS] & 3 62303 /* LViewFlags.InitPhaseStateMask */ 62304 ) === 3 62305 /* InitPhaseState.InitPhaseCompleted */ 62306 ; 62307 62308 if (hooksInitPhaseCompleted) { 62309 const preOrderCheckHooks = tView.preOrderCheckHooks; 62310 62311 if (preOrderCheckHooks !== null) { 62312 executeCheckHooks(lView, preOrderCheckHooks, index); 62313 } 62314 } else {
vendor: 4,068 bytes, lines 62315-62451
62315 const preOrderHooks = tView.preOrderHooks; 62316 62317 if (preOrderHooks !== null) { 62318 executeInitAndCheckHooks(lView, preOrderHooks, 0 62319 /* InitPhaseState.OnInitHooksToBeRun */ 62320 , index); 62321 } 62322 } 62323 } // We must set the selected index *after* running the hooks, because hooks may have side-effects 62324 // that cause other template functions to run, thus updating the selected index, which is global 62325 // state. If we run `setSelectedIndex` *before* we run the hooks, in some cases the selected index 62326 // will be altered by the time we leave the `ɵɵadvance` instruction. 62327 62328 62329 setSelectedIndex(index); 62330} 62331/** 62332 * @license 62333 * Copyright Google LLC All Rights Reserved. 62334 * 62335 * Use of this source code is governed by an MIT-style license that can be 62336 * found in the LICENSE file at https://angular.io/license 62337 */ 62338 62339/** 62340 * A mapping of the @angular/core API surface used in generated expressions to the actual symbols. 62341 * 62342 * This should be kept up to date with the public exports of @angular/core. 62343 */ 62344 62345 62346const angularCoreDiEnv = { 62347 'ɵɵdefineInjectable': ɵɵdefineInjectable, 62348 'ɵɵdefineInjector': ɵɵdefineInjector, 62349 'ɵɵinject': ɵɵinject, 62350 'ɵɵinvalidFactoryDep': ɵɵinvalidFactoryDep, 62351 'resolveForwardRef': resolveForwardRef 62352}; 62353/** 62354 * @license 62355 * Copyright Google LLC All Rights Reserved. 62356 * 62357 * Use of this source code is governed by an MIT-style license that can be 62358 * found in the LICENSE file at https://angular.io/license 62359 */ 62360 62361/** 62362 * Compile an Angular injectable according to its `Injectable` metadata, and patch the resulting 62363 * injectable def (`ɵprov`) onto the injectable type. 62364 */ 62365 62366function compileInjectable(type, meta) { 62367 let ngInjectableDef = null; 62368 let ngFactoryDef = null; // if NG_PROV_DEF is already defined on this class then don't overwrite it 62369 62370 if (!type.hasOwnProperty(NG_PROV_DEF)) { 62371 Object.defineProperty(type, NG_PROV_DEF, { 62372 get: () => { 62373 if (ngInjectableDef === null) { 62374 const compiler = getCompilerFacade({ 62375 usage: 0 62376 /* JitCompilerUsage.Decorator */ 62377 , 62378 kind: 'injectable', 62379 type 62380 }); 62381 ngInjectableDef = compiler.compileInjectable(angularCoreDiEnv, `ng:///${type.name}/ɵprov.js`, getInjectableMetadata(type, meta)); 62382 } 62383 62384 return ngInjectableDef; 62385 } 62386 }); 62387 } // if NG_FACTORY_DEF is already defined on this class then don't overwrite it 62388 62389 62390 if (!type.hasOwnProperty(NG_FACTORY_DEF)) { 62391 Object.defineProperty(type, NG_FACTORY_DEF, { 62392 get: () => { 62393 if (ngFactoryDef === null) { 62394 const compiler = getCompilerFacade({ 62395 usage: 0 62396 /* JitCompilerUsage.Decorator */ 62397 , 62398 kind: 'injectable', 62399 type 62400 }); 62401 ngFactoryDef = compiler.compileFactory(angularCoreDiEnv, `ng:///${type.name}/ɵfac.js`, { 62402 name: type.name, 62403 type, 62404 typeArgumentCount: 0, 62405 deps: reflectDependencies(type), 62406 target: compiler.FactoryTarget.Injectable 62407 }); 62408 } 62409 62410 return ngFactoryDef; 62411 }, 62412 // Leave this configurable so that the factories from directives or pipes can take precedence. 62413 configurable: true 62414 }); 62415 } 62416} 62417 62418const USE_VALUE = getClosureSafeProperty({ 62419 provide: String, 62420 useValue: getClosureSafeProperty 62421}); 62422 62423function isUseClassProvider(meta) { 62424 return meta.useClass !== undefined; 62425} 62426 62427function isUseValueProvider(meta) { 62428 return USE_VALUE in meta; 62429} 62430 62431function isUseFactoryProvider(meta) { 62432 return meta.useFactory !== undefined; 62433} 62434 62435function isUseExistingProvider(meta) { 62436 return meta.useExisting !== undefined; 62437} 62438 62439function getInjectableMetadata(type, srcMeta) { 62440 // Allow the compilation of a class with a `@Injectable()` decorator without parameters 62441 const meta = srcMeta || { 62442 providedIn: null 62443 }; 62444 const compilerMeta = { 62445 name: type.name, 62446 type: type, 62447 typeArgumentCount: 0, 62448 providedIn: meta.providedIn 62449 }; 62450 62451 if ((isUseClassProvider(meta) || isUseFactoryProvider(meta)) && meta.deps !== undefined) {
62452 compilerMeta.deps = convertDependencies(meta.deps); 62453 } // Check to see if the user explicitly provided a `useXxxx` property. 62454 62455 62456 if (isUseClassProvider(meta)) { 62457 compilerMeta.useClass = meta.useClass; 62458 } else if (isUseValueProvider(meta)) { 62459 compilerMeta.useValue = meta.useValue; 62460 } else if (isUseFactoryProvider(meta)) { 62461 compilerMeta.useFactory = meta.useFactory; 62462 } else if (isUseExistingProvider(meta)) { 62463 compilerMeta.useExisting = meta.useExisting; 62464 } 62465 62466 return compilerMeta; 62467} 62468/** 62469 * @license 62470 * Copyright Google LLC All Rights Reserved. 62471 * 62472 * Use of this source code is governed by an MIT-style license that can be 62473 * found in the LICENSE file at https://angular.io/license 62474 */ 62475 62476/** 62477 * Injectable decorator and metadata. 62478 * 62479 * @Annotation 62480 * @publicApi 62481 */ 62482 62483 62484const Injectable = makeDecorator('Injectable', undefined, undefined, undefined, (type, meta) => compileInjectable(type, meta)); 62485/** 62486 * @license 62487 * Copyright Google LLC All Rights Reserved. 62488 * 62489 * Use of this source code is governed by an MIT-style license that can be 62490 * found in the LICENSE file at https://angular.io/license 62491 */ 62492 62493/** 62494 * Create a new `Injector` which is configured using a `defType` of `InjectorType<any>`s. 62495 * 62496 * @publicApi 62497 */ 62498 62499function createInjector(defType, parent = null, additionalProviders = null, name) { 62500 const injector = createInjectorWithoutInjectorInstances(defType, parent, additionalProviders, name); 62501 injector.resolveInjectorInitializers(); 62502 return injector; 62503} 62504/** 62505 * Creates a new injector without eagerly resolving its injector types. Can be used in places 62506 * where resolving the injector types immediately can lead to an infinite loop. The injector types 62507 * should be resolved at a later point by calling `_resolveInjectorDefTypes`. 62508 */ 62509 62510 62511function createInjectorWithoutInjectorInstances(defType, parent = null, additionalProviders = null, name, scopes = new Set()) { 62512 const providers = [additionalProviders || EMPTY_ARRAY, importProvidersFrom(defType)]; 62513 name = name || (typeof defType === 'object' ? undefined : stringify(defType)); 62514 return new R3Injector(providers, parent || getNullInjector(), name || null, scopes); 62515} 62516/** 62517 * @license 62518 * Copyright Google LLC All Rights Reserved. 62519 * 62520 * Use of this source code is governed by an MIT-style license that can be 62521 * found in the LICENSE file at https://angular.io/license 62522 */ 62523 62524/** 62525 * Concrete injectors implement this interface. Injectors are configured 62526 * with [providers](guide/glossary#provider) that associate 62527 * dependencies of various types with [injection tokens](guide/glossary#di-token). 62528 * 62529 * @see ["DI Providers"](guide/dependency-injection-providers). 62530 * @see `StaticProvider` 62531 * 62532 * @usageNotes 62533 * 62534 * The following example creates a service injector instance. 62535 * 62536 * {@example core/di/ts/provider_spec.ts region='ConstructorProvider'} 62537 * 62538 * ### Usage example 62539 * 62540 * {@example core/di/ts/injector_spec.ts region='Injector'} 62541 * 62542 * `Injector` returns itself when given `Injector` as a token: 62543 * 62544 * {@example core/di/ts/injector_spec.ts region='injectInjector'} 62545 * 62546 * @publicApi 62547 */ 62548 62549 62550class Injector { 62551 static create(options, parent) { 62552 if (Array.isArray(options)) { 62553 return createInjector({ 62554 name: '' 62555 }, parent, options, ''); 62556 } else { 62557 const name = options.name ?? ''; 62558 return createInjector({ 62559 name 62560 }, options.parent, options.providers, name); 62561 } 62562 } 62563 62564} 62565 62566Injector.THROW_IF_NOT_FOUND = THROW_IF_NOT_FOUND; 62567Injector.NULL = /* @__PURE__ */new NullInjector(); 62568/** @nocollapse */ 62569 62570Injector.ɵprov = ɵɵdefineInjectable({ 62571 token: Injector, 62572 providedIn: 'any', 62573 factory: () => ɵɵinject(INJECTOR) 62574}); 62575/** 62576 * @internal 62577 * @nocollapse 62578 */ 62579 62580Injector.__NG_ELEMENT_ID__ = -1 62581/* InjectorMarkers.Injector */ 62582; 62583/** 62584 * @license 62585 * Copyright Google LLC All Rights Reserved. 62586 * 62587 * Use of this source code is governed by an MIT-style license that can be 62588 * found in the LICENSE file at https://angular.io/license 62589 */ 62590 62591function findFirstClosedCycle(keys) { 62592 const res = []; 62593 62594 for (let i = 0; i < keys.length; ++i) { 62595 if (res.indexOf(keys[i]) > -1) { 62596 res.push(keys[i]); 62597 return res; 62598 } 62599 62600 res.push(keys[i]); 62601 } 62602 62603 return res; 62604} 62605 62606function constructResolvingPath(keys) { 62607 if (keys.length > 1) { 62608 const reversed = findFirstClosedCycle(keys.slice().reverse()); 62609 const tokenStrs = reversed.map(k => stringify(k.token)); 62610 return ' (' + tokenStrs.join(' -> ') + ')'; 62611 } 62612 62613 return ''; 62614} 62615 62616function injectionError(injector, key, constructResolvingMessage, originalError) { 62617 const keys = [key]; 62618 const errMsg = constructResolvingMessage(keys); 62619 const error = originalError ? wrappedError(errMsg, originalError) : Error(errMsg); 62620 error.addKey = addKey; 62621 error.keys = keys; 62622 error.injectors = [injector]; 62623 error.constructResolvingMessage = constructResolvingMessage; 62624 error[ERROR_ORIGINAL_ERROR] = originalError; 62625 return error; 62626} 62627 62628function addKey(injector, key) { 62629 this.injectors.push(injector); 62630 this.keys.push(key); // Note: This updated message won't be reflected in the `.stack` property 62631 62632 this.message = this.constructResolvingMessage(this.keys); 62633} 62634/** 62635 * Thrown when trying to retrieve a dependency by key from {@link Injector}, but the 62636 * {@link Injector} does not have a {@link Provider} for the given key. 62637 * 62638 * @usageNotes 62639 * ### Example 62640 * 62641 * ```typescript 62642 * class A { 62643 * constructor(b:B) {} 62644 * } 62645 * 62646 * expect(() => Injector.resolveAndCreate([A])).toThrowError(); 62647 * ``` 62648 */ 62649 62650 62651function noProviderError(injector, key) { 62652 return injectionError(injector, key, function (keys) { 62653 const first = stringify(keys[0].token); 62654 return `No provider for ${first}!${constructResolvingPath(keys)}`; 62655 }); 62656} 62657/**
62658 * Thrown when dependencies form a cycle. 62659 * 62660 * @usageNotes 62661 * ### Example 62662 * 62663 * ```typescript 62664 * var injector = Injector.resolveAndCreate([ 62665 * {provide: "one", useFactory: (two) => "two", deps: [[new Inject("two")]]}, 62666 * {provide: "two", useFactory: (one) => "one", deps: [[new Inject("one")]]} 62667 * ]); 62668 * 62669 * expect(() => injector.get("one")).toThrowError(); 62670 * ``` 62671 * 62672 * Retrieving `A` or `B` throws a `CyclicDependencyError` as the graph above cannot be constructed. 62673 */ 62674 62675 62676function cyclicDependencyError(injector, key) { 62677 return injectionError(injector, key, function (keys) { 62678 return `Cannot instantiate cyclic dependency!${constructResolvingPath(keys)}`; 62679 }); 62680} 62681/** 62682 * Thrown when a constructing type returns with an Error. 62683 * 62684 * The `InstantiationError` class contains the original error plus the dependency graph which caused 62685 * this object to be instantiated. 62686 * 62687 * @usageNotes 62688 * ### Example 62689 * 62690 * ```typescript 62691 * class A { 62692 * constructor() { 62693 * throw new Error('message'); 62694 * } 62695 * } 62696 * 62697 * var injector = Injector.resolveAndCreate([A]); 62698 62699 * try { 62700 * injector.get(A); 62701 * } catch (e) { 62702 * expect(e instanceof InstantiationError).toBe(true); 62703 * expect(e.originalException.message).toEqual("message"); 62704 * expect(e.originalStack).toBeDefined(); 62705 * } 62706 * ``` 62707 */ 62708 62709 62710function instantiationError(injector, originalException, originalStack, key) { 62711 return injectionError(injector, key, function (keys) { 62712 const first = stringify(keys[0].token); 62713 return `${originalException.message}: Error during instantiation of ${first}!${constructResolvingPath(keys)}.`; 62714 }, originalException); 62715} 62716/** 62717 * Thrown when an object other then {@link Provider} (or `Type`) is passed to {@link Injector} 62718 * creation. 62719 * 62720 * @usageNotes 62721 * ### Example 62722 * 62723 * ```typescript 62724 * expect(() => Injector.resolveAndCreate(["not a type"])).toThrowError(); 62725 * ``` 62726 */ 62727 62728
62729function invalidProviderError(provider) { 62730 return Error(`Invalid provider - only instances of Provider and Type are allowed, got: ${provider}`); 62731} 62732/** 62733 * Thrown when the class has no annotation information. 62734 * 62735 * Lack of annotation information prevents the {@link Injector} from determining which dependencies 62736 * need to be injected into the constructor. 62737 * 62738 * @usageNotes 62739 * ### Example 62740 * 62741 * ```typescript 62742 * class A { 62743 * constructor(b) {} 62744 * } 62745 * 62746 * expect(() => Injector.resolveAndCreate([A])).toThrowError(); 62747 * ``` 62748 * 62749 * This error is also thrown when the class not marked with {@link Injectable} has parameter types. 62750 * 62751 * ```typescript 62752 * class B {} 62753 * 62754 * class A { 62755 * constructor(b:B) {} // no information about the parameter types of A is available at runtime. 62756 * } 62757 * 62758 * expect(() => Injector.resolveAndCreate([A,B])).toThrowError(); 62759 * ``` 62760 * 62761 */ 62762 62763 62764function noAnnotationError(typeOrFunc, params) { 62765 const signature = []; 62766 62767 for (let i = 0, ii = params.length; i < ii; i++) { 62768 const parameter = params[i]; 62769 62770 if (!parameter || parameter.length == 0) { 62771 signature.push('?'); 62772 } else { 62773 signature.push(parameter.map(stringify).join(' ')); 62774 } 62775 } 62776 62777 return Error('Cannot resolve all parameters for \'' + stringify(typeOrFunc) + '\'(' + signature.join(', ') + '). ' + 'Make sure that all the parameters are decorated with Inject or have valid type annotations and that \'' + stringify(typeOrFunc) + '\' is decorated with Injectable.'); 62778} 62779/** 62780 * Thrown when getting an object by index. 62781 * 62782 * @usageNotes 62783 * ### Example 62784 * 62785 * ```typescript 62786 * class A {} 62787 * 62788 * var injector = Injector.resolveAndCreate([A]); 62789 * 62790 * expect(() => injector.getAt(100)).toThrowError(); 62791 * ``` 62792 * 62793 */ 62794 62795 62796function outOfBoundsError(index) { 62797 return Error(`Index ${index} is out-of-bounds.`); 62798} // TODO: add a working example after alpha38 is released 62799 62800/** 62801 * Thrown when a multi provider and a regular provider are bound to the same token. 62802 * 62803 * @usageNotes 62804 * ### Example 62805 * 62806 * ```typescript 62807 * expect(() => Injector.resolveAndCreate([ 62808 * { provide: "Strings", useValue: "string1", multi: true}, 62809 * { provide: "Strings", useValue: "string2", multi: false} 62810 * ])).toThrowError(); 62811 * ``` 62812 */ 62813 62814 62815function mixingMultiProvidersWithRegularProvidersError(provider1, provider2) { 62816 return Error(`Cannot mix multi providers and regular providers, got: ${provider1} ${provider2}`); 62817} 62818/** 62819 * @license 62820 * Copyright Google LLC All Rights Reserved. 62821 * 62822 * Use of this source code is governed by an MIT-style license that can be 62823 * found in the LICENSE file at https://angular.io/license 62824 */ 62825 62826/** 62827 * A unique object used for retrieving items from the {@link ReflectiveInjector}. 62828 * 62829 * Keys have: 62830 * - a system-wide unique `id`. 62831 * - a `token`. 62832 * 62833 * `Key` is used internally by {@link ReflectiveInjector} because its system-wide unique `id` allows 62834 * the 62835 * injector to store created objects in a more efficient way. 62836 * 62837 * `Key` should not be created directly. {@link ReflectiveInjector} creates keys automatically when 62838 * resolving 62839 * providers. 62840 * 62841 * @deprecated No replacement 62842 * @publicApi 62843 */ 62844 62845 62846class ReflectiveKey { 62847 /** 62848 * Private 62849 */ 62850 constructor(token, id) { 62851 this.token = token; 62852 this.id = id; 62853 62854 if (!token) { 62855 throw new RuntimeError(208 62856 /* RuntimeErrorCode.MISSING_INJECTION_TOKEN */ 62857 , ngDevMode && 'Token must be defined!'); 62858 } 62859 62860 this.displayName = stringify(this.token); 62861 } 62862 /** 62863 * Retrieves a `Key` for a token. 62864 */ 62865 62866 62867 static get(token) { 62868 return _globalKeyRegistry.get(resolveForwardRef(token)); 62869 } 62870 /** 62871 * @returns the number of keys registered in the system. 62872 */ 62873 62874 62875 static get numberOfKeys() { 62876 return _globalKeyRegistry.numberOfKeys; 62877 } 62878 62879} 62880 62881class KeyRegistry { 62882 constructor() { 62883 this._allKeys = new Map(); 62884 } 62885 62886 get(token) { 62887 if (token instanceof ReflectiveKey) return token; 62888 62889 if (this._allKeys.has(token)) { 62890 return this._allKeys.get(token); 62891 } 62892 62893 const newKey = new ReflectiveKey(token, ReflectiveKey.numberOfKeys); 62894 62895 this._allKeys.set(token, newKey); 62896 62897 return newKey; 62898 } 62899 62900 get numberOfKeys() { 62901 return this._allKeys.size; 62902 } 62903 62904} 62905 62906const _globalKeyRegistry = new KeyRegistry(); 62907/** 62908 * @license 62909 * Copyright Google LLC All Rights Reserved. 62910 * 62911 * Use of this source code is governed by an MIT-style license that can be 62912 * found in the LICENSE file at https://angular.io/license 62913 */ 62914 62915/** 62916 * `Dependency` is used by the framework to extend DI. 62917 * This is internal to Angular and should not be used directly. 62918 */ 62919 62920 62921class ReflectiveDependency { 62922 constructor(key, optional, visibility) { 62923 this.key = key; 62924 this.optional = optional; 62925 this.visibility = visibility; 62926 } 62927 62928 static fromKey(key) { 62929 return new ReflectiveDependency(key, false, null); 62930 } 62931 62932} 62933 62934const _EMPTY_LIST = []; 62935 62936class ResolvedReflectiveProvider_ { 62937 constructor(key, resolvedFactories, multiProvider) { 62938 this.key = key; 62939 this.resolvedFactories = resolvedFactories; 62940 this.multiProvider = multiProvider; 62941 this.resolvedFactory = this.resolvedFactories[0]; 62942 } 62943 62944} 62945/** 62946 * An internal resolved representation of a factory function created by resolving `Provider`. 62947 * @publicApi 62948 */ 62949 62950 62951class ResolvedReflectiveFactory { 62952 constructor( 62953 /** 62954 * Factory function which can return an instance of an object represented by a key. 62955 */ 62956 factory, 62957 /** 62958 * Arguments (dependencies) to the `factory` function. 62959 */ 62960 dependencies) { 62961 this.factory = factory;
62962 this.dependencies = dependencies; 62963 } 62964 62965} 62966/** 62967 * Resolve a single provider. 62968 */ 62969 62970 62971function resolveReflectiveFactory(provider) { 62972 let factoryFn; 62973 let resolvedDeps; 62974 62975 if (provider.useClass) { 62976 const useClass = resolveForwardRef(provider.useClass); 62977 factoryFn = getReflect().factory(useClass); 62978 resolvedDeps = _dependenciesFor(useClass); 62979 } else if (provider.useExisting) { 62980 factoryFn = aliasInstance => aliasInstance; 62981 62982 resolvedDeps = [ReflectiveDependency.fromKey(ReflectiveKey.get(provider.useExisting))]; 62983 } else if (provider.useFactory) { 62984 factoryFn = provider.useFactory; 62985 resolvedDeps = constructDependencies(provider.useFactory, provider.deps); 62986 } else { 62987 factoryFn = () => provider.useValue; 62988 62989 resolvedDeps = _EMPTY_LIST; 62990 } 62991 62992 return new ResolvedReflectiveFactory(factoryFn, resolvedDeps); 62993} 62994/** 62995 * Converts the `Provider` into `ResolvedProvider`. 62996 * 62997 * `Injector` internally only uses `ResolvedProvider`, `Provider` contains convenience provider 62998 * syntax. 62999 */ 63000 63001 63002function resolveReflectiveProvider(provider) { 63003 return new ResolvedReflectiveProvider_(ReflectiveKey.get(provider.provide), [resolveReflectiveFactory(provider)], provider.multi || false); 63004} 63005/** 63006 * Resolve a list of Providers. 63007 */ 63008 63009 63010function resolveReflectiveProviders(providers) { 63011 const normalized = _normalizeProviders(providers, []); 63012 63013 const resolved = normalized.map(resolveReflectiveProvider); 63014 const resolvedProviderMap = mergeResolvedReflectiveProviders(resolved, new Map()); 63015 return Array.from(resolvedProviderMap.values()); 63016} 63017/** 63018 * Merges a list of ResolvedProviders into a list where each key is contained exactly once and 63019 * multi providers have been merged. 63020 */ 63021 63022 63023function mergeResolvedReflectiveProviders(providers, normalizedProvidersMap) { 63024 for (let i = 0; i < providers.length; i++) { 63025 const provider = providers[i]; 63026 const existing = normalizedProvidersMap.get(provider.key.id); 63027 63028 if (existing) { 63029 if (provider.multiProvider !== existing.multiProvider) { 63030 throw mixingMultiProvidersWithRegularProvidersError(existing, provider); 63031 } 63032 63033 if (provider.multiProvider) { 63034 for (let j = 0; j < provider.resolvedFactories.length; j++) { 63035 existing.resolvedFactories.push(provider.resolvedFactories[j]); 63036 } 63037 } else { 63038 normalizedProvidersMap.set(provider.key.id, provider); 63039 } 63040 } else { 63041 let resolvedProvider; 63042 63043 if (provider.multiProvider) { 63044 resolvedProvider = new ResolvedReflectiveProvider_(provider.key, provider.resolvedFactories.slice(), provider.multiProvider); 63045 } else { 63046 resolvedProvider = provider; 63047 } 63048 63049 normalizedProvidersMap.set(provider.key.id, resolvedProvider); 63050 } 63051 } 63052 63053 return normalizedProvidersMap; 63054} 63055 63056function _normalizeProviders(providers, res) { 63057 providers.forEach(b => { 63058 if (b instanceof Type) { 63059 res.push({ 63060 provide: b, 63061 useClass: b 63062 }); 63063 } else if (b && typeof b == 'object' && b.provide !== undefined) { 63064 res.push(b); 63065 } else if (Array.isArray(b)) { 63066 _normalizeProviders(b, res); 63067 } else { 63068 throw invalidProviderError(b); 63069 } 63070 }); 63071 return res; 63072} 63073 63074function constructDependencies(typeOrFunc, dependencies) { 63075 if (!dependencies) { 63076 return _dependenciesFor(typeOrFunc); 63077 } else { 63078 const params = dependencies.map(t => [t]); 63079 return dependencies.map(t => _extractToken(typeOrFunc, t, params)); 63080 } 63081} 63082 63083function _dependenciesFor(typeOrFunc) { 63084 const params = getReflect().parameters(typeOrFunc); 63085 if (!params) return []; 63086 63087 if (params.some(p => p == null)) { 63088 throw noAnnotationError(typeOrFunc, params); 63089 } 63090 63091 return params.map(p => _extractToken(typeOrFunc, p, params)); 63092} 63093 63094function _extractToken(typeOrFunc, metadata, params) { 63095 let token = null; 63096 let optional = false;
63097 63098 if (!Array.isArray(metadata)) { 63099 if (metadata instanceof Inject) { 63100 return _createDependency(metadata.token, optional, null); 63101 } else { 63102 return _createDependency(metadata, optional, null); 63103 } 63104 } 63105 63106 let visibility = null; 63107 63108 for (let i = 0; i < metadata.length; ++i) { 63109 const paramMetadata = metadata[i]; 63110 63111 if (paramMetadata instanceof Type) { 63112 token = paramMetadata; 63113 } else if (paramMetadata instanceof Inject) { 63114 token = paramMetadata.token; 63115 } else if (paramMetadata instanceof Optional) { 63116 optional = true; 63117 } else if (paramMetadata instanceof Self || paramMetadata instanceof SkipSelf) { 63118 visibility = paramMetadata; 63119 } else if (paramMetadata instanceof InjectionToken) { 63120 token = paramMetadata; 63121 } 63122 } 63123 63124 token = resolveForwardRef(token); 63125 63126 if (token != null) { 63127 return _createDependency(token, optional, visibility); 63128 } else { 63129 throw noAnnotationError(typeOrFunc, params); 63130 } 63131} 63132 63133function _createDependency(token, optional, visibility) { 63134 return new ReflectiveDependency(ReflectiveKey.get(token), optional, visibility); 63135} 63136/** 63137 * @license 63138 * Copyright Google LLC All Rights Reserved. 63139 * 63140 * Use of this source code is governed by an MIT-style license that can be 63141 * found in the LICENSE file at https://angular.io/license 63142 */ 63143// Threshold for the dynamic version 63144 63145 63146const UNDEFINED = {}; 63147/** 63148 * A ReflectiveDependency injection container used for instantiating objects and resolving 63149 * dependencies. 63150 * 63151 * An `Injector` is a replacement for a `new` operator, which can automatically resolve the 63152 * constructor dependencies. 63153 * 63154 * In typical use, application code asks for the dependencies in the constructor and they are 63155 * resolved by the `Injector`. 63156 * 63157 * @usageNotes 63158 * ### Example 63159 * 63160 * The following example creates an `Injector` configured to create `Engine` and `Car`. 63161 * 63162 * ```typescript 63163 * @Injectable() 63164 * class Engine { 63165 * } 63166 * 63167 * @Injectable() 63168 * class Car { 63169 * constructor(public engine:Engine) {} 63170 * } 63171 * 63172 * var injector = ReflectiveInjector.resolveAndCreate([Car, Engine]); 63173 * var car = injector.get(Car); 63174 * expect(car instanceof Car).toBe(true); 63175 * expect(car.engine instanceof Engine).toBe(true); 63176 * ``` 63177 * 63178 * Notice, we don't use the `new` operator because we explicitly want to have the `Injector` 63179 * resolve all of the object's dependencies automatically. 63180 * 63181 * TODO: delete in v14. 63182 * 63183 * @deprecated from v5 - slow and brings in a lot of code, Use `Injector.create` instead. 63184 * @publicApi 63185 */ 63186 63187class ReflectiveInjector { 63188 /** 63189 * Turns an array of provider definitions into an array of resolved providers. 63190 * 63191 * A resolution is a process of flattening multiple nested arrays and convert
63191ing individual 63192 * providers into an array of `ResolvedReflectiveProvider`s. 63193 * 63194 * @usageNotes 63195 * ### Example 63196 * 63197 * ```typescript 63198 * @Injectable() 63199 * class Engine { 63200 * } 63201 * 63202 * @Injectable() 63203 * class Car { 63204 * constructor(public engine:Engine) {} 63205 * } 63206 * 63207 * var providers = ReflectiveInjector.resolve([Car, [[Engine]]]); 63208 * 63209 * expect(providers.length).toEqual(2); 63210 * 63211 * expect(providers[0] instanceof ResolvedReflectiveProvider).toBe(true); 63212 * expect(providers[0].key.displayName).toBe("Car"); 63213 * expect(providers[0].dependencies.length).toEqual(1); 63214 * expect(providers[0].factory).toBeDefined(); 63215 * 63216 * expect(providers[1].key.displayName).toBe("Engine"); 63217 * }); 63218 * ``` 63219 * 63220 */ 63221 static resolve(providers) { 63222 return resolveReflectiveProviders(providers); 63223 } 63224 /** 63225 * Resolves an array of providers and creates an injector from those providers. 63226 * 63227 * The passed-in providers can be an array of `Type`, `Provider`, 63228 * or a recursive array of more providers. 63229 * 63230 * @usageNotes 63231 * ### Example 63232 * 63233 * ```typescript 63234 * @Injectable() 63235 * class Engine { 63236 * } 63237 * 63238 * @Injectable() 63239 * class Car { 63240 * constructor(public engine:Engine) {} 63241 * } 63242 * 63243 * var injector = ReflectiveInjector.resolveAndCreate([Car, Engine]); 63244 * expect(injector.get(Car) instanceof Car).toBe(true); 63245 * ``` 63246 */ 63247 63248 63249 static resolveAndCreate(providers, parent) { 63250 const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers); 63251 return ReflectiveInjector.fromResolvedProviders(ResolvedReflectiveProviders, parent); 63252 } 63253 /** 63254 * Creates an injector from previously resolved providers. 63255 * 63256 * This API is the recommended way to construct injectors in performance-sensitive parts. 63257 * 63258 * @usageNotes 63259 * ### Example 63260 * 63261 * ```typescript 63262 * @Injectable() 63263 * class Engine { 63264 * } 63265 * 63266 * @Injectable() 63267 * class Car { 63268 * constructor(public engine:Engine) {} 63269 * } 63270 * 63271 * var providers = ReflectiveInjector.resolve([Car, Engine]); 63272 * var injector = ReflectiveInjector.fromResolvedProviders(providers); 63273 * expect(injector.get(Car) instanceof Car).toBe(true); 63274 * ``` 63275 */ 63276 63277 63278 static fromResolvedProviders(providers, parent) { 63279 return new ReflectiveInjector_(providers, parent); 63280 } 63281 63282} 63283 63284class ReflectiveInjector_ { 63285 /** 63286 * Private 63287 */ 63288 constructor(_providers, _parent) { 63289 /** @internal */ 63290 this._constructionCounter = 0; 63291 this._providers = _providers; 63292 this.parent = _parent || null; 63293 const len = _providers.length; 63294 this.keyIds = []; 63295 this.objs = []; 63296 63297 for (let i = 0; i < len; i++) { 63298 this.keyIds[i] = _providers[i].key.id; 63299 this.objs[i] = UNDEFINED; 63300 } 63301 } 63302 63303 get(token, notFoundValue = THROW_IF_NOT_FOUND) { 63304 return this._getByKey(ReflectiveKey.get(token), null, notFoundValue); 63305 } 63306 63307 resolveAndCreateChild(providers) { 63308 const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers); 63309 return this.createChildFromResolved(ResolvedReflectiveProviders); 63310 } 63311 63312 createChildFromResolved(providers) { 63313 const inj = new ReflectiveInjector_(providers); 63314 inj.parent = this; 63315 return inj; 63316 } 63317 63318 resolveAndInstantiate(provider) { 63319 return this.instantiateResolved(ReflectiveInjector.resolve([provider])[0]); 63320 } 63321 63322 instantiateResolved(provider) { 63323 return this._instantiateProvider(provider); 63324 } 63325 63326 getProviderAtIndex(index) { 63327 if (index < 0 || index >= this._providers.length) { 63328 throw outOfBoundsError(index); 63329 } 63330 63331 return this._providers[index]; 63332 } 63333 /** @internal */ 63334 63335 63336 _new(provider) { 63337 if (this._constructionCounter++ > this._getMaxNumberOfObjects()) { 63338 throw cyclicDependencyError(this, provider.key); 63339 } 63340 63341 return this._instantiateProvider(provider); 63342 } 63343 63344 _getMaxNumberOfObjects() { 63345 return this.objs.length; 63346 } 63347 63348 _instantiateProvider(provider) { 63349 if (provider.multiProvider) { 63350 const res = []; 63351 63352 for (let i = 0; i < provider.resolvedFactories.length; ++i) { 63353 res[i] = this._instantiate(provider, provider.resolvedFactories[i]); 63354 } 63355 63356 return res; 63357 } else { 63358 return this._instantiate(provider, provider.resolvedFactories[0]); 63359 } 63360 } 63361 63362 _instantiate(provider, ResolvedReflectiveFactory) { 63363 const factory = ResolvedReflectiveFactory.factory; 63364 let deps; 63365 63366 try { 63367 deps = ResolvedReflectiveFactory.dependencies.map(dep => this._getByReflectiveDependency(dep)); 63368 } catch (e) { 63369 if (e.addKey) { 63370 e.addKey(this, provider.key); 63371 } 63372 63373 throw e; 63374 } 63375 63376 let obj; 63377 63378 try { 63379 obj = factory(...deps); 63380 } catch (e) { 63381 throw instantiationError(this, e, e.stack, provider.key); 63382 } 63383 63384 return obj; 63385 } 63386 63387 _getByReflectiveDependency(dep) { 63388 return this._getByKey(dep.key, dep.visibility, dep.optional ? null : THROW_IF_NOT_FOUND); 63389 } 63390 63391 _getByKey(key, visibility, notFoundValue) { 63392 if (key === ReflectiveInjector_.INJECTOR_KEY) { 63393 return this; 63394 } 63395 63396 if (visibility instanceof Self) { 63397 return this._getByKeySelf(key, notFoundValue); 63398 } else { 63399 return this._getByKeyDefault(key, notFoundValue, visibility); 63400 } 63401 } 63402 63403 _getObjByKeyId(keyId) { 63404 for (let i = 0; i < this.keyIds.length; i++) { 63405 if (this.keyIds[i] === keyId) { 63406 if (this.objs[i] === UNDEFINED) { 63407 this.objs[i] = this._new(this._providers[i]); 63408 } 63409 63410 return this.objs[i]; 63411 } 63412 } 63413 63414 return UNDEFINED; 63415 } 63416 /** @internal */ 63417 63418 63419 _throwOrNull(key, notFoundValue) { 63420 if (notFoundValue !== THROW_IF_NOT_FOUND) { 63421 return notFoundValue; 63422 } else { 63423 throw noProviderError(this, key); 63424 } 63425 } 63426 /** @internal */ 63427 63428 63429 _getByKeySelf(key, notFoundValue) { 63430 const obj = this._getObjByKeyId(key.id); 63431 63432 return obj !== UNDEFINED ? obj : this._throwOrNull(key, notFoundValue); 63433 } 63434 /** @internal */ 63435 63436 63437 _getByKeyDefault(key, notFoundValue, visibility) { 63438 let inj; 63439 63440 if (visibility instanceof SkipSelf) { 63441 inj = this.parent; 63442 } else { 63443 inj = this; 63444 } 63445 63446 while (inj instanceof ReflectiveInjector_) { 63447 const inj_ = inj; 63448 63449 const obj = inj_._getObjByKeyId(key.id); 63450 63451 if (obj !== UNDEFINED) return obj; 63452 inj = inj_.parent; 63453 } 63454 63455 if (inj !== null) { 63456 return inj.get(key.token, notFoundValue); 63457 } else { 63458 return this._throwOrNull(key, notFoundValue); 63459 } 63460 } 63461 63462 get displayName() { 63463 const providers = _mapProviders(this, b => ' "' + b.key.displayName + '" ').join(', '); 63464
63465 return `ReflectiveInjector(providers: [${providers}])`; 63466 } 63467 63468 toString() { 63469 return this.displayName; 63470 } 63471 63472} 63473 63474ReflectiveInjector_.INJECTOR_KEY = /* @__PURE__ */ReflectiveKey.get(Injector); 63475 63476function _mapProviders(injector, fn) { 63477 const res = []; 63478 63479 for (let i = 0; i < injector._providers.length; ++i) { 63480 res[i] = fn(injector.getProviderAtIndex(i)); 63481 } 63482 63483 return res; 63484} 63485/** 63486 * @license 63487 * Copyright Google LLC All Rights Reserved. 63488 * 63489 * Use of this source code is governed by an MIT-style license that can be 63490 * found in the LICENSE file at https://angular.io/license 63491 */ 63492 63493/** 63494 * @license 63495 * Copyright Google LLC All Rights Reserved. 63496 * 63497 * Use of this source code is governed by an MIT-style license that can be 63498 * found in the LICENSE file at https://angular.io/license 63499 */ 63500 63501/** 63502 * @license 63503 * Copyright Google LLC All Rights Reserved. 63504 * 63505 * Use of this source code is governed by an MIT-style license that can be 63506 * found in the LICENSE file at https://angular.io/license 63507 */ 63508 63509 63510function ɵɵdirectiveInject(token, flags = InjectFlags.Default) { 63511 const lView = getLView(); // Fall back to inject() if view hasn't been created. This situation can happen in tests 63512 // if inject utilities are used before bootstrapping. 63513 63514 if (lView === null) { 63515 // Verify that we will not get into infinite loop. 63516 ngDevMode && assertInjectImplementationNotEqual(ɵɵdirectiveInject); 63517 return ɵɵinject(token, flags); 63518 } 63519 63520 const tNode = getCurrentTNode(); 63521 return getOrCreateInjectable(tNode, lView, resolveForwardRef(token), flags); 63522} 63523/** 63524 * Throws an error indicating that a factory function could not be generated by the compiler for a 63525 * particular class. 63526 * 63527 * This instruction allows the actual error message to be optimized away when ngDevMode is turned 63528 * off, saving bytes of generated code while still providing a good experience in dev mode. 63529 * 63530 * The name of the class is not mentioned here, but will be in the generated factory function name 63531 * and thus in the stack trace. 63532 * 63533 * @codeGenApi 63534 */ 63535 63536 63537function ɵɵinvalidFactory() { 63538 const msg = ngDevMode ? `This constructor was not compatible with Dependency Injection.` : 'invalid'; 63539 throw new Error(msg); 63540} 63541/** 63542 * @license 63543 * Copyright Google LLC All Rights Reserved. 63544 * 63545 * Use of this source code is governed by an MIT-style license that can be 63546 * found in the LICENSE file at https://angular.io/license 63547 */ 63548 63549/** 63550 * THIS FILE CONTAINS CODE WHICH SHOULD BE TREE SHAKEN AND NEVER CALLED FROM PRODUCTION CODE!!! 63551 */ 63552 63553/** 63554 * Creates an `Array` construction with a given name. This is useful when 63555 * looking for memory consumption to see what time of array it is. 63556 * 63557 * 63558 * @param name Name to give to the constructor 63559 * @returns A subclass of `Array` if possible. This can only be done in 63560 * environments which support `class` construct. 63561 */ 63562 63563 63564function createNamedArrayType(name) { 63565 // This should never be called in prod mode, so let's verify that is the case. 63566 if (ngDevMode) { 63567 try { 63568 // If this function were compromised the following could lead to arbitrary 63569 // script execution. We bless it with Trusted Types anyway since this 63570 // function is stripped out of production binaries. 63571 return newTrustedFunctionForDev('Array', `return class ${name} extends Array{}`)(Array); 63572 } catch (e) { 63573 // If it does not work just give up and fall back to regular Array. 63574 return Array; 63575 } 63576 } else { 63577 throw new Error('Looks like we are in \'prod mode\', but we are creating a named Array type, which is wrong! Check your code'); 63578 } 63579} 63580/** 63581 * @license 63582 * Copyright Google LLC All Rights Reserved. 63583 * 63584 * Use of this source code is governed by an MIT-style license that can be 63585 * found in the LICENSE file at https://angular.io/license 63586 */ 63587 63588 63589function toTStylingRange(prev, next) { 63590 ngDevMode && assertNumberInRange(prev, 0, 32767 63591 /* StylingRange.UNSIGNED_MASK */ 63592 ); 63593 ngDevMode && assertNumberInRange(next, 0, 32767 63594 /* StylingRange.UNSIGNED_MASK */ 63595 ); 63596 return prev << 17 63597 /* StylingRange.PREV_SHIFT */ 63598 | next << 2 63599 /* StylingRange.NEXT_SHIFT */ 63600 ; 63601} 63602 63603function getTStylingRangePrev(tStylingRange) { 63604 ngDevMode && assertNumber(tStylingRange, 'expected number'); 63605 return tStylingRange >> 17
vendor: 1,591 bytes, lines 63606-63666
63606 /* StylingRange.PREV_SHIFT */ 63607 & 32767 63608 /* StylingRange.UNSIGNED_MASK */ 63609 ; 63610} 63611 63612function getTStylingRangePrevDuplicate(tStylingRange) { 63613 ngDevMode && assertNumber(tStylingRange, 'expected number'); 63614 return (tStylingRange & 2 63615 /* StylingRange.PREV_DUPLICATE */ 63616 ) == 2 63617 /* StylingRange.PREV_DUPLICATE */ 63618 ; 63619} 63620 63621function setTStylingRangePrev(tStylingRange, previous) { 63622 ngDevMode && assertNumber(tStylingRange, 'expected number'); 63623 ngDevMode && assertNumberInRange(previous, 0, 32767 63624 /* StylingRange.UNSIGNED_MASK */ 63625 ); 63626 return tStylingRange & ~4294836224 63627 /* StylingRange.PREV_MASK */ 63628 | previous << 17 63629 /* StylingRange.PREV_SHIFT */ 63630 ; 63631} 63632 63633function setTStylingRangePrevDuplicate(tStylingRange) { 63634 ngDevMode && assertNumber(tStylingRange, 'expected number'); 63635 return tStylingRange | 2 63636 /* StylingRange.PREV_DUPLICATE */ 63637 ; 63638} 63639 63640function getTStylingRangeNext(tStylingRange) { 63641 ngDevMode && assertNumber(tStylingRange, 'expected number'); 63642 return (tStylingRange & 131068 63643 /* StylingRange.NEXT_MASK */ 63644 ) >> 2 63645 /* StylingRange.NEXT_SHIFT */ 63646 ; 63647} 63648 63649function setTStylingRangeNext(tStylingRange, next) { 63650 ngDevMode && assertNumber(tStylingRange, 'expected number'); 63651 ngDevMode && assertNumberInRange(next, 0, 32767 63652 /* StylingRange.UNSIGNED_MASK */ 63653 ); 63654 return tStylingRange & ~131068 63655 /* StylingRange.NEXT_MASK */ 63656 | // 63657 next << 2 63658 /* StylingRange.NEXT_SHIFT */ 63659 ; 63660} 63661 63662function getTStylingRangeNextDuplicate(tStylingRange) { 63663 ngDevMode && assertNumber(tStylingRange, 'expected number'); 63664 return (tStylingRange & 1 63665 /* StylingRange.NEXT_DUPLICATE */ 63666 ) === 1
63667 /* StylingRange.NEXT_DUPLICATE */ 63668 ; 63669} 63670 63671function setTStylingRangeNextDuplicate(tStylingRange) { 63672 ngDevMode && assertNumber(tStylingRange, 'expected number'); 63673 return tStylingRange | 1 63674 /* StylingRange.NEXT_DUPLICATE */ 63675 ; 63676} 63677 63678function getTStylingRangeTail(tStylingRange) { 63679 ngDevMode && assertNumber(tStylingRange, 'expected number'); 63680 const next = getTStylingRangeNext(tStylingRange); 63681 return next === 0 ? getTStylingRangePrev(tStylingRange) : next; 63682} 63683/** 63684 * @license 63685 * Copyright Google LLC All Rights Reserved. 63686 * 63687 * Use of this source code is governed by an MIT-style license that can be 63688 * found in the LICENSE file at https://angular.io/license 63689 */ 63690 63691/** 63692 * Patch a `debug` property on top of the existing object. 63693 * 63694 * NOTE: always call this method with `ngDevMode && attachDebugObject(...)` 63695 * 63696 * @param obj Object to patch 63697 * @param debug Value to patch 63698 */ 63699 63700 63701function attachDebugObject(obj, debug) { 63702 if (ngDevMode) { 63703 Object.defineProperty(obj, 'debug', { 63704 value: debug, 63705 enumerable: false 63706 }); 63707 } else { 63708 throw new Error('This method should be guarded with `ngDevMode` so that it can be tree shaken in production!'); 63709 } 63710} 63711/** 63712 * Patch a `debug` property getter on top of the existing object. 63713 * 63714 * NOTE: always call this method with `ngDevMode && attachDebugObject(...)` 63715 * 63716 * @param obj Object to patch 63717 * @param debugGetter Getter returning a value to patch 63718 */ 63719 63720 63721function attachDebugGetter(obj, debugGetter) { 63722 if (ngDevMode) { 63723 Object.defineProperty(obj, 'debug', { 63724 get: debugGetter, 63725 enumerable: false 63726 }); 63727 } else { 63728 throw new Error('This method should be guarded with `ngDevMode` so that it can be tree shaken in production!'); 63729 } 63730} 63731/** 63732 * @license 63733 * Copyright Google LLC All Rights Reserved. 63734 * 63735 * Use of this source code is governed by an MIT-style license that can be 63736 * found in the LICENSE file at https://angular.io/license 63737 */ 63738 63739/* 63740 * This file contains conditionally attached classes which provide human readable (debug) level 63741 * information for `LView`, `LContainer` and other internal data structures. These data structures 63742 * are stored internally as array which makes it very difficult during debugging to reason about the 63743 * current state of the system. 63744 * 63745 * Patching the array with extra property does change the array's hidden class' but it does not 63746 * change the cost of access, therefore this patching should not have significant if any impact in 63747 * `ngDevMode` mode. (see: https://jsperf.com/array-vs-monkey-patch-array) 63748 * 63749 * So instead of seeing: 63750 * ``` 63751 * Array(30) [Object, 659, null, â¦] 63752 * ``` 63753 * 63754 * You get to see: 63755 * ``` 63756 * LViewDebug { 63757 * views: [...], 63758 * flags: {attached: true, ...} 63759 * nodes: [ 63760 * {html: '<div id="123">', ..., nodes: [ 63761 * {html: '<span>', ..., nodes: null} 63762 * ]} 63763 * ] 63764 * } 63765 * ``` 63766 */ 63767 63768 63769let LVIEW_COMPONENT_CACHE; 63770let LVIEW_EMBEDDED_CACHE; 63771let LVIEW_ROOT; 63772let LVIEW_COMPONENT; 63773let LVIEW_EMBEDDED; 63774/** 63775 * This function clones a blueprint and creates LView. 63776 * 63777 * Simple slice will keep the same type, and we need it to be LView 63778 */ 63779 63780function cloneToLViewFromTViewBlueprint(tView) { 63781 const debugTView = tView; 63782 const lView = getLViewToClone(debugTView.type, tView.template && tView.template.name); 63783 return lView.concat(tView.blueprint); 63784} 63785 63786class LRootView extends Array {} 63787 63788class LComponentView extends Array {} 63789 63790class LEmbeddedView extends Array {} 63791 63792function getLViewToClone(type, name) { 63793 switch (type) { 63794 case 0 63795 /* TViewType.Root */ 63796 : 63797 if (LVIEW_ROOT === undefined) LVIEW_ROOT = new LRootView(); 63798 return LVIEW_ROOT; 63799 63800 case 1 63801 /* TViewType.Component */ 63802 : 63803 if (!ngDevMode || !ngDevMode.namedConstructors) { 63804 if (LVIEW_COMPONENT === undefined) LVIEW_COMPONENT = new LComponentView(); 63805 return LVIEW_COMPONENT; 63806 } 63807 63808 if (LVIEW_COMPONENT_CACHE === undefined) LVIEW_COMPONENT_CACHE = new Map(); 63809 let componentArray = LVIEW_COMPONENT_CACHE.get(name); 63810 63811 if (componentArray === undefined) { 63812 componentArray = new (createNamedArrayType('LComponentView' + nameSuffix(name)))(); 63813 LVIEW_COMPONENT_CACHE.set(name, componentArray); 63814 } 63815 63816 return componentArray; 63817 63818 case 2 63819 /* TViewType.Embedded */ 63820 : 63821 if (!ngDevMode || !ngDevMode.namedConstructors) { 63822 if (LVIEW_EMBEDDED === undefined) LVIEW_EMBEDDED = new LEmbeddedView(); 63823 return LVIEW_EMBEDDED; 63824 } 63825 63826 if (LVIEW_EMBEDDED_CACHE === undefined) LVIEW_EMBEDDED_CACHE = new Map(); 63827 let embeddedArray = LVIEW_EMBEDDED_CACHE.get(name); 63828 63829 if (embeddedArray === undefined) { 63830 embeddedArray = new (createNamedArrayType('LEmbeddedView' + nameSuffix(name)))(); 63831 LVIEW_EMBEDDED_CACHE.set(name, embeddedArray); 63832 } 63833 63834 return embeddedArray; 63835 } 63836} 63837 63838function nameSuffix(text) { 63839 if (text == null) return ''; 63840 const index = text.lastIndexOf('_Template'); 63841 return '_' + (index === -1 ? text : text.slice(0, index)); 63842} 63843/** 63844 * This class is a debug version of Object literal so that we can have constructor name show up 63845 * in 63846 * debug tools in ngDevMode. 63847 */ 63848 63849 63850const TViewConstructor = class TView { 63851 constructor(type, blueprint, template, queries, viewQuery, declTNode, data, bindingStartIndex, expandoStartIndex, hostBindingOpCodes, firstCreatePass, firstUpdatePass, staticViewQueries, staticContentQueries, preOrderHooks, preOrderCheckHooks, contentHooks, c
63851ontentCheckHooks, viewHooks, viewCheckHooks, destroyHooks, cleanup, contentQueries, components, directiveRegistry, pipeRegistry, firstChild, schemas, consts, incompleteFirstPass, _decls, _vars) { 63852 this.type = type; 63853 this.blueprint = blueprint; 63854 this.template = template; 63855 this.queries = queries; 63856 this.viewQuery = viewQuery; 63857 this.declTNode = declTNode; 63858 this.data = data; 63859 this.bindingStartIndex = bindingStartIndex; 63860 this.expandoStartIndex = expandoStartIndex; 63861 this.hostBindingOpCodes = hostBindingOpCodes; 63862 this.firstCreatePass = firstCreatePass; 63863 this.firstUpdatePass = firstUpdatePass; 63864 this.staticViewQueries = staticViewQueries; 63865 this.staticContentQueries = staticContentQueries; 63866 this.preOrderHooks = preOrderHooks; 63867 this.preOrderCheckHooks = preOrderCheckHooks; 63868 this.contentHooks = contentHooks; 63869 this.contentCheckHooks = contentCheckHooks; 63870 this.viewHooks = viewHooks; 63871 this.viewCheckHooks = viewCheckHooks; 63872 this.destroyHooks = destroyHooks; 63873 this.cleanup = cleanup; 63874 this.contentQueries = contentQueries; 63875 this.components = components; 63876 this.directiveRegistry = directiveRegistry; 63877 this.pipeRegistry = pipeRegistry; 63878 this.firstChild = firstChild; 63879 this.schemas = schemas; 63880 this.consts = consts; 63881 this.incompleteFirstPass = incompleteFirstPass; 63882 this._decls = _decls; 63883 this._vars = _vars; 63884 } 63885 63886 get template_() { 63887 const buf = []; 63888 processTNodeChildren(this.firstChild, buf); 63889 return buf.join(''); 63890 } 63891 63892 get type_() { 63893 return TViewTypeAsString[this.type] || `TViewType.?${this.type}?`; 63894 } 63895 63896}; 63897 63898class TNode { 63899 constructor(tView_, // 63900 type, // 63901 index, // 63902 insertBeforeIndex, // 63903 injectorIndex, // 63904 directiveStart, // 63905 directiveEnd, // 63906 directiveStylingLast, // 63907 propertyBindings, // 63908 flags, // 63909 providerIndexes, // 63910 value, // 63911 attrs, // 63912 mergedAttrs, // 63913 localNames, // 63914 initialInputs, // 63915 inputs, // 63916 outputs, // 63917 tViews, // 63918 next, // 63919 projectionNext, // 63920 child, // 63921 parent, // 63922 projection, // 63923 styles, // 63924 stylesWithoutHost, // 63925 residualStyles, // 63926 classes, // 63927 classesWithoutHost, // 63928 residualClasses, // 63929 classBindings, // 63930 styleBindings) { 63931 this.tView_ = tView_; 63932 this.type = type; 63933 this.index = index; 63934 this.insertBeforeIndex = insertBeforeIndex; 63935 this.injectorIndex = injectorIndex; 63936 this.directiveStart = directiveStart; 63937 this.directiveEnd = directiveEnd; 63938 this.directiveStylingLast = directiveStylingLast; 63939 this.propertyBindings = propertyBindings; 63940 this.flags = flags; 63941 this.providerIndexes = providerIndexes; 63942 this.value = value; 63943 this.attrs = attrs; 63944 this.mergedAttrs = mergedAttrs; 63945 this.localNames = localNames; 63946 this.initialInputs = initialInputs; 63947 this.inputs = inputs; 63948 this.outputs = outputs; 63949 this.tViews = tViews; 63950 this.next = next; 63951 this.projectionNext = projectionNext; 63952 this.child = child; 63953 this.parent = parent; 63954 this.projection = projection; 63955 this.styles = styles; 63956 this.stylesWithoutHost = stylesWithoutHost; 63957 this.residualStyles = residualStyles; 63958 this.classes = classes; 63959 this.classesWithoutHost = classesWithoutHost; 63960 this.residualClasses = residualClasses; 63961 this.classBindings = classBindings; 63962 this.styleBindings = styleBindings; 63963 } 63964 /** 63965 * Return a human debug version of the set of `NodeInjector`s which will be consulted when 63966 * resolving tokens from this `TNode`. 63967 * 63968 * When debugging applications, it is often difficult to determine which `NodeInjector`s will be 63969 * consulted. This method shows a list of `DebugNode`s representing the `TNode`s which will be 63970 * consulted in order when resolving a token starting at this `TNode`. 63971 * 63972 * The original data is stored in `LView` and `TView` with a lot of offset indexes, and so it is 63973 * difficult to reason about. 63974 * 63975 * @param lView The `LView` instance for this `TNode`. 63976 */ 63977 63978 63979 debugNodeInjectorPath(lView) { 63980 const path = []; 63981 let injectorIndex = getInjectorIndex(this, lView); 63982 63983 if (injectorIndex === -1) { 63984 // Looks like the current `TNode` does not have `NodeInjector` associated with it => look for 63985 // parent NodeInjector. 63986 const parentLocation = getParentInjectorLocation(this, lView); 63987 63988 if (parentLocation !== NO_PARENT_INJECTOR) { 63989 // We found a parent, so start searching from the parent location. 63990 injectorIndex = getParentInjectorIndex(parentLocation);
63991 lView = getParentInjectorView(parentLocation, lView); 63992 } else {// No parents have been found, so there are no `NodeInjector`s to consult. 63993 } 63994 } 63995 63996 while (injectorIndex !== -1) { 63997 ngDevMode && assertNodeInjector(lView, injectorIndex); 63998 const tNode = lView[TVIEW].data[injectorIndex + 8 63999 /* NodeInjectorOffset.TNODE */ 64000 ]; 64001 path.push(buildDebugNode(tNode, lView)); 64002 const parentLocation = lView[injectorIndex + 8 64003 /* NodeInjectorOffset.PARENT */ 64004 ]; 64005 64006 if (parentLocation === NO_PARENT_INJECTOR) { 64007 injectorIndex = -1; 64008 } else { 64009 injectorIndex = getParentInjectorIndex(parentLocation); 64010 lView = getParentInjectorView(parentLocation, lView); 64011 } 64012 } 64013 64014 return path; 64015 } 64016 64017 get type_() { 64018 return toTNodeTypeAsString(this.type) || `TNodeType.?${this.type}?`; 64019 } 64020 64021 get flags_() { 64022 const flags = []; 64023 if (this.flags & 16 64024 /* TNodeFlags.hasClassInput */ 64025 ) flags.push('TNodeFlags.hasClassInput'); 64026 if (this.flags & 8 64027 /* TNodeFlags.hasContentQuery */ 64028 ) flags.push('TNodeFlags.hasContentQuery'); 64029 if (this.flags & 32 64030 /* TNodeFlags.hasStyleInput */ 64031 ) flags.push('TNodeFlags.hasStyleInput'); 64032 if (this.flags & 128 64033 /* TNodeFlags.hasHostBindings */ 64034 ) flags.push('TNodeFlags.hasHostBindings'); 64035 if (this.flags & 2 64036 /* TNodeFlags.isComponentHost */ 64037 ) flags.push('TNodeFlags.isComponentHost'); 64038 if (this.flags & 1 64039 /* TNodeFlags.isDirectiveHost */ 64040 ) flags.push('TNodeFlags.isDirectiveHost'); 64041 if (this.flags & 64 64042 /* TNodeFlags.isDetached */ 64043 ) flags.push('TNodeFlags.isDetached'); 64044 if (this.flags & 4 64045 /* TNodeFlags.isProjected */ 64046 ) flags.push('TNodeFlags.isProjected'); 64047 return flags.join('|'); 64048 } 64049 64050 get template_() { 64051 if (this.type & 1 64052 /* TNodeType.Text */ 64053 ) return this.value; 64054 const buf = []; 64055 const tagName = typeof this.value === 'string' && this.value || this.type_; 64056 buf.push('<', tagName); 64057 64058 if (this.flags) { 64059 buf.push(' ', this.flags_); 64060 } 64061 64062 if (this.attrs) { 64063 for (let i = 0; i < this.attrs.length;) { 64064 const attrName = this.attrs[i++]; 64065 64066 if (typeof attrName == 'number') { 64067 break; 64068 } 64069 64070 const attrValue = this.attrs[i++]; 64071 buf.push(' ', attrName, '="', attrValue, '"'); 64072 } 64073 } 64074 64075 buf.push('>'); 64076 processTNodeChildren(this.child, buf); 64077 buf.push('</', tagName, '>'); 64078 return buf.join(''); 64079 } 64080 64081 get styleBindings_() { 64082 return toDebugStyleBinding(this, false); 64083 } 64084 64085 get classBindings_() { 64086 return toDebugStyleBinding(this, true); 64087 } 64088 64089 get providerIndexStart_() { 64090 return this.providerIndexes & 1048575 64091 /* TNodeProviderIndexes.ProvidersStartIndexMask */ 64092 ; 64093 } 64094 64095 get providerIndexEnd_() { 64096 return this.providerIndexStart_ + (this.providerIndexes >>> 20 64097 /* TNodeProviderIndexes.CptViewProvidersCountShift */ 64098 ); 64099 } 64100 64101} 64102 64103const TNodeDebug = TNode; 64104 64105function toDebugStyleBinding(tNode, isClassBased) { 64106 const tData = tNode.tView_.data; 64107 const bindings = []; 64108 const range = isClassBased ? tNode.classBindings : tNode.styleBindings; 64109 const prev = getTStylingRangePrev(range); 64110 const next = getTStylingRangeNext(range); 64111 let isTemplate = next !== 0; 64112 let cursor = isTemplate ? next : prev; 64113 64114 while (cursor !== 0) { 64115 const itemKey = tData[cursor]; 64116 const itemRange = tData[cursor + 1]; 64117 bindings.unshift({ 64118 key: itemKey, 64119 index: cursor, 64120 isTemplate: isTemplate, 64121 prevDuplicate: getTStylingRangePrevDuplicate(itemRange), 64122 nextDuplicate: getTStylingRangeNextDuplicate(itemRange), 64123 nextIndex: getTStylingRangeNext(itemRange), 64124 prevIndex: getTStylingRangePrev(itemRange) 64125 }); 64126 if (cursor === prev) isTemplate = false; 64127 cursor = getTStylingRangePrev(itemRange); 64128 } 64129 64130 bindings.push((isClassBased ? tNode.residualClasses : tNode.residualStyles) || null); 64131 return bindings; 64132} 64133 64134function processTNodeChildren(tNode, buf) { 64135 while (tNode) { 64136 buf.push(tNode.template_); 64137 tNode = tNode.next; 64138 } 64139} 64140 64141class TViewData extends Array {} 64142 64143let TVIEWDATA_EMPTY; // can't initialize here or it will not be tree shaken, because 64144// `LView` constructor could have side-effects. 64145 64146/** 64147 * This function clones a blueprint and creates TData. 64148 * 64149 * Simple slice will keep the same type, and we need it to be TData 64150 */ 64151 64152function cloneToTViewData(list) { 64153 if (TVIEWDATA_EMPTY === undefined) TVIEWDATA_EMPTY = new TViewData(); 64154 return TVIEWDATA_EMPTY.concat(list); 64155} 64156 64157class LViewBlueprint extends Array {} 64158 64159class MatchesArray extends Array {} 64160 64161class TViewComponents extends Array {} 64162 64163class TNodeLocalNames extends Array {} 64164 64165class TNodeInitialInputs extends Array {} 64166 64167class LCleanup extends Array {} 64168 64169class TCleanup extends Array {} 64170 64171function attachLViewDebug(lView) { 64172 attachDebugObject(lView, new LViewDebug(lView)); 64173} 64174 64175function attachLContainerDebug(lContainer) { 64176 attachDebugObject(lContainer, new LContainerDebug(lContainer)); 64177} 64178 64179function toDebug(obj) { 64180 if (obj) { 64181 const debug = obj.debug; 64182 assertDefined(debug, 'Object does not have a debug representation.'); 64183 return debug; 64184 } else { 64185 return obj; 64186 } 64187} 64188/** 64189 * Use this method to unwrap a native element in `LView` and convert it into HTML for easier 64190 * reading. 64191 * 64192 * @param value possibly wrapped native DOM node. 64193 * @param includeChildren If `true` then the serialized HTML form will include child elements 64194 * (same 64195 * as `outerHTML`). If `false` then the serialized HTML form will only contain the element 64196 * itself 64197 * (will not serialize child elements). 64198 */ 64199 64200 64201function toHtml(value, includeChildren = false) { 64202 const node = unwrapRNode(value); 64203 64204 if (node) { 64205 switch (node.nodeType) { 64206 case Node.TEXT_NODE: 64207 return node.textContent; 64208 64209 case Node.COMMENT_NODE: 64210 return `<!--${node.textContent}-->`; 64211 64212 case Node.ELEMENT_NODE: 64213 const outerHTML = node.outerHTML; 64214 64215 if (includeChildren) { 64216 return outerHTML; 64217 } else { 64218 const innerHTML = '>' + node.innerHTML + '<'; 64219 return outerHTML.split(innerHTML)[0] + '>'; 64220 } 64221 64222 } 64223 } 64224 64225 return null; 64226} 64227 64228class LViewDebug { 64229 constructor(_raw_lView) { 64230 this._raw_lView = _raw_lView; 64231 } 64232 /** 64233 * Flags associated with the `LView` unpacked into a more readable state. 64234 */ 64235 64236 64237 get flags() { 64238 const flags = this._raw_lView[FLAGS]; 64239 return { 64240 __raw__flags__: flags, 64241 initPhaseState: flags & 3 64242 /* LViewFlags.InitPhaseStateMask */ 64243 , 64244 creationMode: !!(flags & 4 64245 /* LViewFlags.CreationMode */ 64246 ), 64247 firstViewPass: !!(flags & 8 64248 /* LViewFlags.FirstLViewPass */ 64249 ), 64250 checkAlways: !!(flags & 16 64251 /* LViewFlags.CheckAlways */ 64252 ), 64253 dirty: !!(flags & 32 64254 /* LViewFlags.Dirty */ 64255 ), 64256 attached: !!(flags & 64 64257 /* LViewFlags.Attached */ 64258 ), 64259 destroyed: !!(flags & 128 64260 /* LViewFlags.Destroyed */ 64261 ), 64262 isRoot: !!(flags & 256 64263 /* LViewFlags.IsRoot */ 64264 ), 64265 indexWithinInitPhase: flags >> 11 64266 /* LViewFlags.IndexWithinInitPhaseShift */ 64267 64268 }; 64269 } 64270 64271 get parent() { 64272 return toDebug(this._raw_lView[PARENT]); 64273 } 64274 64275 get hostHTML() { 64276 return toHtml(this._raw_lView[HOST], true); 64277 } 64278 64279 get html() { 64280 return (this.nodes || []).map(mapToHTML).join(''); 64281 } 64282 64283 get context() { 64284 return this._raw_lView[CONTEXT]; 64285 } 64286 /** 64287 * The tree of nodes associated with the current `LView`. The nodes have been normalized into 64288 * a tree structure with relevant details pulled out for readability. 64289 */ 64290 64291 64292 get nodes() { 64293 const lView = this._raw_lView; 64294 const tNode = lView[TVIEW].firstChild; 64295 return toDebugNodes(tNode, lView); 64296 } 64297 64298 get template() { 64299 return this.tView.template_; 64300 } 64301 64302 get tView() { 64303 return this._raw_lView[TVIEW]; 64304 } 64305 64306 get cleanup() { 64307 return this._raw_lView[CLEANUP]; 64308 } 64309 64310 get injector() { 64311 return this._raw_lView[INJECTOR$1]; 64312 } 64313 64314 get rendererFactory() { 64315 return this._raw_lView[RENDERER_FACTORY]; 64316 } 64317 64318 get renderer() { 64319 return this._raw_lView[RENDERER]; 64320 } 64321 64322 get sanitizer() { 64323 return this._raw_lView[SANITIZER]; 64324 } 64325 64326 get childHead() { 64327 return toDebug(this._raw_lView[CHILD_HEAD]); 64328 } 64329 64330 get next() { 64331 return toDebug(this._raw_lView[NEXT]); 64332 } 64333 64334 get childTail() { 64335 return toDebug(this._raw_lView[CHILD_TAIL]); 64336 } 64337 64338 get declarationView() { 64339 return toDebug(this._raw_lView[DECLARATION_VIEW]); 64340 } 64341 64342 get queries() { 64343 return this._raw_lView[QUERIES]; 64344 } 64345 64346 get tHost() { 64347 return this._raw_lView[T_HOST]; 64348 } 64349 64350 get id() { 64351 return this._raw_lView[ID]; 64352 } 64353 64354 get decls() { 64355 return toLViewRange(this.tView, this._raw_lView, HEADER_OFFSET, this.tView.bindingStartIndex); 64356 } 64357 64358 get vars() { 64359 return toLViewRange(this.tView, this._raw_lView, this.tView.bindingStartIndex, this.tView.expandoStartIndex); 64360 } 64361 64362 get expando() { 64363 return toLViewRange(this.tView, this._raw_lView, this.tView.expandoStartIndex, this._raw_lView.length); 64364 } 64365 /**
64366 * Normalized view of child views (and containers) attached at this location. 64367 */ 64368 64369 64370 get childViews() { 64371 const childViews = []; 64372 let child = this.childHead; 64373 64374 while (child) { 64375 childViews.push(child); 64376 child = child.next; 64377 } 64378 64379 return childViews; 64380 } 64381 64382} 64383 64384function mapToHTML(node) { 64385 if (node.type === 'ElementContainer') { 64386 return (node.children || []).map(mapToHTML).join(''); 64387 } else if (node.type === 'IcuContainer') { 64388 throw new Error('Not implemented'); 64389 } else { 64390 return toHtml(node.native, true) || ''; 64391 } 64392} 64393 64394function toLViewRange(tView, lView, start, end) { 64395 let content = []; 64396 64397 for (let index = start; index < end; index++) { 64398 content.push({ 64399 index: index, 64400 t: tView.data[index], 64401 l: lView[index] 64402 }); 64403 } 64404 64405 return { 64406 start: start, 64407 end: end, 64408 length: end - start, 64409 content: content 64410 }; 64411} 64412/** 64413 * Turns a flat list of nodes into a tree by walking the associated `TNode` tree. 64414 * 64415 * @param tNode 64416 * @param lView 64417 */ 64418 64419 64420function toDebugNodes(tNode, lView) { 64421 if (tNode) { 64422 const debugNodes = []; 64423 let tNodeCursor = tNode; 64424 64425 while (tNodeCursor) { 64426 debugNodes.push(buildDebugNode(tNodeCursor, lView)); 64427 tNodeCursor = tNodeCursor.next; 64428 } 64429 64430 return debugNodes; 64431 } else { 64432 return []; 64433 } 64434} 64435 64436function buildDebugNode(tNode, lView) { 64437 const rawValue = lView[tNode.index]; 64438 const native = unwrapRNode(rawValue); 64439 const factories = []; 64440 const instances = []; 64441 const tView = lView[TVIEW]; 64442 64443 for (let i = tNode.directiveStart; i < tNode.directiveEnd; i++) { 64444 const def = tView.data[i]; 64445 factories.push(def.type); 64446 instances.push(lView[i]); 64447 } 64448 64449 return { 64450 html: toHtml(native), 64451 type: toTNodeTypeAsString(tNode.type), 64452 tNode, 64453 native: native, 64454 children: toDebugNodes(tNode.child, lView), 64455 factories, 64456 instances, 64457 injector: buildNodeInjectorDebug(tNode, tView, lView), 64458 64459 get injectorResolutionPath() { 64460 return tNode.debugNodeInjectorPath(lView); 64461 } 64462 64463 }; 64464} 64465 64466function buildNodeInjectorDebug(tNode, tView, lView) { 64467 const viewProviders = []; 64468 64469 for (let i = tNode.providerIndexStart_; i < tNode.providerIndexEnd_; i++) { 64470 viewProviders.push(tView.data[i]); 64471 } 64472 64473 const providers = []; 64474 64475 for (let i = tNode.providerIndexEnd_; i < tNode.directiveEnd; i++) { 64476 providers.push(tView.data[i]); 64477 } 64478 64479 const nodeInjectorDebug = { 64480 bloom: toBloom(lView, tNode.injectorIndex), 64481 cumulativeBloom: toBloom(tView.data, tNode.injectorIndex), 64482 providers, 64483 viewProviders, 64484 parentInjectorIndex: lView[tNode.providerIndexStart_ - 1] 64485 }; 64486 return nodeInjectorDebug; 64487} 64488/** 64489 * Convert a number at `idx` location in `array` into binary representation. 64490 * 64491 * @param array 64492 * @param idx 64493 */ 64494 64495 64496function binary(array, idx) { 64497 const value = array[idx]; // If not a number we print 8 `?` to retain alignment but let user know that it was called on 64498 // wrong type. 64499 64500 if (typeof value !== 'number') return '????????'; // We prefix 0s so that we have constant length number 64501 64502 const text = '00000000' + value.toString(2); 64503 return text.substring(text.length - 8); 64504} 64505/** 64506 * Convert a bloom filter at location `idx` in `array` into binary representation. 64507 * 64508 * @param array 64509 * @param idx 64510 */ 64511 64512 64513function toBloom(array, idx) { 64514 if (idx < 0) { 64515 return 'NO_NODE_INJECTOR'; 64516 } 64517 64518 return `${binary(array, idx + 7)}_${binary(array, idx + 6)}_${binary(array, idx + 5)}_${binary(array, idx + 4)}_${binary(array, idx + 3)}_${binary(array, idx + 2)}_${binary(array, idx + 1)}_${binary(array, idx + 0)}`; 64519} 64520 64521class LContainerDebug { 64522 constructor(_raw_lContainer) { 64523 this._raw_lContainer = _raw_lContainer; 64524 } 64525 64526 get hasTransplantedViews() { 64527 return this._raw_lContainer[HAS_TRANSPLANTED_VIEWS]; 64528 } 64529 64530 get views() { 64531 return this._raw_lContainer.slice(CONTAINER_HEADER_OFFSET).map(toDebug); 64532 } 64533 64534 get parent() { 64535 return toDebug(this._raw_lContainer[PARENT]); 64536 } 64537 64538 get movedViews() { 64539 return this._raw_lContainer[MOVED_VIEWS]; 64540 } 64541 64542 get host() { 64543 return this._raw_lContainer[HOST]; 64544 } 64545 64546 get native() { 64547 return this._raw_lContainer[NATIVE]; 64548 } 64549 64550 get next() { 64551 return toDebug(this._raw_lContainer[NEXT]); 64552 } 64553 64554} 64555/** 64556 * @license 64557 * Copyright Google LLC All Rights Reserved. 64558 * 64559 * Use of this source code is governed by an MIT-style license that can be 64560 * found in the LICENSE file at https://angular.io/license 64561 */ 64562 64563/** 64564 * Invoke `HostBindingsFunction`s for view. 64565 * 64566 * This methods executes `TView.hostBindingOpCodes`. It is used to execute the 64567 * `HostBindingsFunction`s associated with the current `LView`. 64568 * 64569 * @param tView Current `TView`. 64570 * @param lView Current `LView`. 64571 */ 64572 64573 64574function processHostBindingOpCodes(tView, lView) { 64575 const hostBindingOpCodes = tView.hostBindingOpCodes; 64576 if (hostBindingOpCodes === null) return; 64577 64578 try { 64579 for (let i = 0; i < hostBindingOpCodes.length; i++) { 64580 const opCode = hostBindingOpCodes[i]; 64581 64582 if (opCode < 0) { 64583 // Negative numbers are element indexes. 64584 setSelectedIndex(~opCode); 64585 } else { 64586 // Positive numbers are NumberTuple which store bindingRootIndex and directiveIndex. 64587 const directiveIdx = opCode; 64588 const bindingRootIndx = hostBindingOpCodes[++i]; 64589 const hostBindingFn = hostBindingOpCodes[++i]; 64590 setBindingRootForHostBindings(bindingRootIndx, directiveIdx); 64591 const context = lView[directiveIdx]; 64592 hostBindingFn(2 64593 /* RenderFlags.Update */ 64594 , context); 64595 } 64596 } 64597 } finally { 64598 setSelectedIndex(-1); 64599 } 64600} 64601/** Refreshes all content queries declared by directives in a given view */ 64602 64603 64604function refreshContentQueries(tView, lView) { 64605 const contentQueries = tView.contentQueries; 64606 64607 if (contentQueries !== null) { 64608 for (let i = 0; i < contentQueries.length; i += 2) { 64609 const queryStartIdx = contentQueries[i]; 64610 const directiveDefIdx = contentQueries[i + 1]; 64611 64612 if (directiveDefIdx !== -1) { 64613 const directiveDef = tView.data[directiveDefIdx]; 64614 ngDevMode && assertDefined(directiveDef, 'DirectiveDef not found.'); 64615 ngDevMode && assertDefined(directiveDef.contentQueries, 'contentQueries function should be defined'); 64616 setCurrentQueryIndex(queryStartIdx); 64617 directiveDef.contentQueries(2 64618 /* RenderFlags.Update */ 64619 , lView[directiveDefIdx], directiveDefIdx); 64620 } 64621 } 64622 } 64623} 64624/** Refreshes child components in the current view (update mode). */ 64625 64626 64627function refreshChildComponents(hostLView, components) { 64628 for (let i = 0; i < components.length; i++) { 64629 refreshComponent(hostLView, components[i]); 64630 } 64631} 64632/** Renders child components in the current view (creation mode). */ 64633 64634 64635function renderChildComponents(hostLView, components) { 64636 for (let i = 0; i < components.length; i++) { 64637 renderComponent(hostLView, components[i]); 64638 } 64639} 64640 64641function createLView(parentLView, tView, context, flags, host, tHostNode, rendererFactory, renderer, sanitizer, injector, embeddedViewInjector) { 64642 const lView = ngDevMode ? cloneToLViewFromTViewBlueprint(tView) : tView.blueprint.slice(); 64643 lView[HOST] = host; 64644 lView[FLAGS] = flags | 4 64645 /* LViewFlags.CreationMode */ 64646 | 64 64647 /* LViewFlags.Attached */ 64648 | 8 64649 /* LViewFlags.FirstLViewPass */ 64650 ; 64651 64652 if (embeddedViewInjector !== null || parentLView && parentLView[FLAGS] & 1024 64653 /* LViewFlags.HasEmbeddedViewInjector */ 64654 ) { 64655 lView[FLAGS] |= 1024 64656 /* LViewFlags.HasEmbeddedViewInjector */ 64657 ; 64658 } 64659 64660 resetPreOrderHookFlags(lView); 64661 ngDevMode && tView.declTNode && parentLView && assertTNodeForLView(tView.declTNode, parentLView); 64662 lView[PARENT] = lView[DECLARATION_VIEW] = parentLView; 64663 lView[CONTEXT] = context; 64664 lView[RENDERER_FACTORY] = rendererFactory || parentLView && parentLView[RENDERER_FACTORY]; 64665 ngDevMode && assertDefined(lView[RENDERER_FACTORY], 'RendererFactory is required'); 64666 lView[RENDERER] = renderer || parentLView && parentLView[RENDERER]; 64667 ngDevMode && assertDefined(lView[RENDERER], 'Renderer is required');
vendor: 18,305 bytes, lines 64668-65183
64668 lView[SANITIZER] = sanitizer || parentLView && parentLView[SANITIZER] || null; 64669 lView[INJECTOR$1] = injector || parentLView && parentLView[INJECTOR$1] || null; 64670 lView[T_HOST] = tHostNode; 64671 lView[ID] = getUniqueLViewId(); 64672 lView[EMBEDDED_VIEW_INJECTOR] = embeddedViewInjector; 64673 ngDevMode && assertEqual(tView.type == 2 64674 /* TViewType.Embedded */ 64675 ? parentLView !== null : true, true, 'Embedded views must have parentLView'); 64676 lView[DECLARATION_COMPONENT_VIEW] = tView.type == 2 64677 /* TViewType.Embedded */ 64678 ? parentLView[DECLARATION_COMPONENT_VIEW] : lView; 64679 ngDevMode && attachLViewDebug(lView); 64680 return lView; 64681} 64682 64683function getOrCreateTNode(tView, index, type, name, attrs) { 64684 ngDevMode && index !== 0 && // 0 are bogus nodes and they are OK. See `createContainerRef` in 64685 // `view_engine_compatibility` for additional context. 64686 assertGreaterThanOrEqual(index, HEADER_OFFSET, 'TNodes can\'t be in the LView header.'); // Keep this function short, so that the VM will inline it. 64687 64688 ngDevMode && assertPureTNodeType(type); 64689 let tNode = tView.data[index]; 64690 64691 if (tNode === null) { 64692 tNode = createTNodeAtIndex(tView, index, type, name, attrs); 64693 64694 if (isInI18nBlock()) { 64695 // If we are in i18n block then all elements should be pre declared through `Placeholder` 64696 // See `TNodeType.Placeholder` and `LFrame.inI18n` for more context. 64697 // If the `TNode` was not pre-declared than it means it was not mentioned which means it was 64698 // removed, so we mark it as detached. 64699 tNode.flags |= 64 64700 /* TNodeFlags.isDetached */ 64701 ; 64702 } 64703 } else if (tNode.type & 64 64704 /* TNodeType.Placeholder */ 64705 ) { 64706 tNode.type = type; 64707 tNode.value = name; 64708 tNode.attrs = attrs; 64709 const parent = getCurrentParentTNode(); 64710 tNode.injectorIndex = parent === null ? -1 : parent.injectorIndex; 64711 ngDevMode && assertTNodeForTView(tNode, tView); 64712 ngDevMode && assertEqual(index, tNode.index, 'Expecting same index'); 64713 } 64714 64715 setCurrentTNode(tNode, true); 64716 return tNode; 64717} 64718 64719function createTNodeAtIndex(tView, index, type, name, attrs) { 64720 const currentTNode = getCurrentTNodePlaceholderOk(); 64721 const isParent = isCurrentTNodeParent(); 64722 const parent = isParent ? currentTNode : currentTNode && currentTNode.parent; // Parents cannot cross component boundaries because components will be used in multiple places. 64723 64724 const tNode = tView.data[index] = createTNode(tView, parent, type, index, name, attrs); // Assign a pointer to the first child node of a given view. The first node is not always the one 64725 // at index 0, in case of i18n, index 0 can be the instruction `i18nStart` and the first node has 64726 // the index 1 or more, so we can't just check node index. 64727 64728 if (tView.firstChild === null) { 64729 tView.firstChild = tNode; 64730 } 64731 64732 if (currentTNode !== null) { 64733 if (isParent) { 64734 // FIXME(misko): This logic looks unnecessarily complicated. Could we simplify? 64735 if (currentTNode.child == null && tNode.parent !== null) { 64736 // We are in the same view, which means we are adding content node to the parent view. 64737 currentTNode.child = tNode; 64738 } 64739 } else { 64740 if (currentTNode.next === null) { 64741 // In the case of i18n the `currentTNode` may already be linked, in which case we don't want 64742 // to break the links which i18n created. 64743 currentTNode.next = tNode; 64744 } 64745 } 64746 } 64747 64748 return tNode; 64749} 64750/** 64751 * When elements are created dynamically after a view blueprint is created (e.g. through 64752 * i18nApply()), we need to adjust the blueprint for future 64753 * template passes. 64754 * 64755 * @param tView `TView` associated with `LView` 64756 * @param lView The `LView` containing the blueprint to adjust 64757 * @param numSlotsToAlloc The number of slots to alloc in the LView, should be >0 64758 * @param initialValue Initial value to store in blueprint 64759 */ 64760 64761 64762function allocExpando(tView, lView, numSlotsToAlloc, initialValue) { 64763 if (numSlotsToAlloc === 0) return -1; 64764 64765 if (ngDevMode) { 64766 assertFirstCreatePass(tView); 64767 assertSame(tView, lView[TVIEW], '`LView` must be associated with `TView`!'); 64768 assertEqual(tView.data.length, lView.length, 'Expecting LView to be same size as TView'); 64769 assertEqual(tView.data.length, tView.blueprint.length, 'Expecting Blueprint to be same size as TView'); 64770 assertFirstUpdatePass(tView); 64771 } 64772 64773 const allocIdx = lView.length; 64774 64775 for (let i = 0; i < numSlotsToAlloc; i++) { 64776 lView.push(initialValue); 64777 tView.blueprint.push(initialValue); 64778 tView.data.push(null); 64779 } 64780 64781 return allocIdx; 64782} ////////////////////////// 64783//// Render 64784////////////////////////// 64785 64786/** 64787 * Processes a view in the creation mode. This includes a number of steps in a specific order: 64788 * - creating view query functions (if any); 64789 * - executing a template function in the creation mode; 64790 * - updating static queries (if any); 64791 * - creating child components defined in a given view. 64792 */ 64793 64794 64795function renderView(tView, lView, context) { 64796 ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode'); 64797 enterView(lView); 64798 64799 try { 64800 const viewQuery = tView.viewQuery; 64801 64802 if (viewQuery !== null) { 64803 executeViewQueryFn(1 64804 /* RenderFlags.Create */ 64805 , viewQuery, context); 64806 } // Execute a template associated with this view, if it exists. A template function might not be 64807 // defined for the root component views. 64808 64809 64810 const templateFn = tView.template; 64811 64812 if (templateFn !== null) { 64813 executeTemplate(tView, lView, templateFn, 1 64814 /* RenderFlags.Create */ 64815 , context); 64816 } // This needs to be set before children are processed to support recursive components. 64817 // This must be set to false immediately after the first creation run because in an 64818 // ngFor loop, all the views will be created together before update mode runs and turns 64819 // off firstCreatePass. If we don't set it here, instances will perform directive 64820 // matching, etc again and again. 64821 64822 64823 if (tView.firstCreatePass) { 64824 tView.firstCreatePass = false; 64825 } // We resolve content queries specifically marked as `static` in creation mode. Dynamic 64826 // content queries are resolved during change detection (i.e. update mode), after embedded 64827 // views are refreshed (see block above). 64828 64829 64830 if (tView.staticContentQueries) { 64831 refreshContentQueries(tView, lView); 64832 } // We must materialize query results before child components are processed 64833 // in case a child component has projected a container. The LContainer needs 64834 // to exist so the embedded views are properly attached by the container. 64835 64836 64837 if (tView.staticViewQueries) { 64838 executeViewQueryFn(2 64839 /* RenderFlags.Update */ 64840 , tView.viewQuery, context); 64841 } // Render child component views. 64842 64843 64844 const components = tView.components; 64845 64846 if (components !== null) { 64847 renderChildComponents(lView, components); 64848 } 64849 } catch (error) { 64850 // If we didn't manage to get past the first template pass due to 64851 // an error, mark the view as corrupted so we can try to recover. 64852 if (tView.firstCreatePass) { 64853 tView.incompleteFirstPass = true; 64854 tView.firstCreatePass = false; 64855 } 64856 64857 throw error; 64858 } finally { 64859 lView[FLAGS] &= ~4 64860 /* LViewFlags.CreationMode */ 64861 ; 64862 leaveView(); 64863 } 64864} 64865/** 64866 * Processes a view in update mode. This includes a number of steps in a specific order: 64867 * - executing a template function in update mode; 64868 * - executing hooks; 64869 * - refreshing queries; 64870 * - setting host bindings; 64871 * - refreshing child (embedded and component) views. 64872 */ 64873 64874 64875function refreshView(tView, lView, templateFn, context) { 64876 ngDevMode && assertEqual(isCreationMode(lView), false, 'Should be run in update mode'); 64877 const flags = lView[FLAGS]; 64878 if ((flags & 128 64879 /* LViewFlags.Destroyed */ 64880 ) === 128 64881 /* LViewFlags.Destroyed */ 64882 ) return; 64883 enterView(lView); // Check no changes mode is a dev only mode used to verify that bindings have not changed 64884 // since they were assigned. We do not want to execute lifecycle hooks in that mode. 64885 64886 const isInCheckNoChangesPass = ngDevMode && isInCheckNoChangesMode(); 64887 64888 try { 64889 resetPreOrderHookFlags(lView); 64890 setBindingIndex(tView.bindingStartIndex); 64891 64892 if (templateFn !== null) { 64893 executeTemplate(tView, lView, templateFn, 2 64894 /* RenderFlags.Update */ 64895 , context); 64896 } 64897 64898 const hooksInitPhaseCompleted = (flags & 3 64899 /* LViewFlags.InitPhaseStateMask */ 64900 ) === 3 64901 /* InitPhaseState.InitPhaseCompleted */ 64902 ; // execute pre-order hooks (OnInit, OnChanges, DoCheck) 64903 // PERF WARNING: do NOT extract this to a separate function without running benchmarks 64904 64905 if (!isInCheckNoChangesPass) { 64906 if (hooksInitPhaseCompleted) { 64907 const preOrderCheckHooks = tView.preOrderCheckHooks; 64908 64909 if (preOrderCheckHooks !== null) { 64910 executeCheckHooks(lView, preOrderCheckHooks, null); 64911 } 64912 } else { 64913 const preOrderHooks = tView.preOrderHooks; 64914 64915 if (preOrderHooks !== null) { 64916 executeInitAndCheckHooks(lView, preOrderHooks, 0 64917 /* InitPhaseState.OnInitHooksToBeRun */ 64918 , null); 64919 } 64920 64921 incrementInitPhaseFlags(lView, 0 64922 /* InitPhaseState.OnInitHooksToBeRun */ 64923 ); 64924 } 64925 } // First mark transplanted views that are declared in this lView as needing a refresh at their 64926 // insertion points. This is needed to avoid the situation where the template is defined in this 64927 // `LView` but its declaration appears after the insertion component. 64928 64929 64930 markTransplantedViewsForRefresh(lView); 64931 refreshEmbeddedViews(lView); // Content query results must be refreshed before content hooks are called. 64932 64933 if (tView.contentQueries !== null) { 64934 refreshContentQueries(tView, lView); 64935 } // execute content hooks (AfterContentInit, AfterContentChecked) 64936 // PERF WARNING: do NOT extract this to a separate function without running benchmarks 64937 64938 64939 if (!isInCheckNoChangesPass) { 64940 if (hooksInitPhaseCompleted) { 64941 const contentCheckHooks = tView.contentCheckHooks; 64942 64943 if (contentCheckHooks !== null) { 64944 executeCheckHooks(lView, contentCheckHooks); 64945 } 64946 } else { 64947 const contentHooks = tView.contentHooks; 64948 64949 if (contentHooks !== null) { 64950 executeInitAndCheckHooks(lView, contentHooks, 1 64951 /* InitPhaseState.AfterContentInitHooksToBeRun */ 64952 ); 64953 } 64954 64955 incrementInitPhaseFlags(lView, 1 64956 /* InitPhaseState.AfterContentInitHooksToBeRun */ 64957 ); 64958 } 64959 } 64960 64961 processHostBindingOpCodes(tView, lView); // Refresh child component views. 64962 64963 const components = tView.components; 64964 64965 if (components !== null) { 64966 refreshChildComponents(lView, components); 64967 } // View queries must execute after refreshing child components because a template in this view 64968 // could be inserted in a child component. If the view query executes before child component 64969 // refresh, the template might not yet be inserted. 64970 64971 64972 const viewQuery = tView.viewQuery; 64973 64974 if (viewQuery !== null) { 64975 executeViewQueryFn(2 64976 /* RenderFlags.Update */ 64977 , viewQuery, context); 64978 } // execute view hooks (AfterViewInit, AfterViewChecked) 64979 // PERF WARNING: do NOT extract this to a separate function without running benchmarks 64980 64981 64982 if (!isInCheckNoChangesPass) { 64983 if (hooksInitPhaseCompleted) { 64984 const viewCheckHooks = tView.viewCheckHooks; 64985 64986 if (viewCheckHooks !== null) { 64987 executeCheckHooks(lView, viewCheckHooks); 64988 } 64989 } else { 64990 const viewHooks = tView.viewHooks; 64991 64992 if (viewHooks !== null) { 64993 executeInitAndCheckHooks(lView, viewHooks, 2 64994 /* InitPhaseState.AfterViewInitHooksToBeRun */ 64995 ); 64996 } 64997 64998 incrementInitPhaseFlags(lView, 2 64999 /* InitPhaseState.AfterViewInitHooksToBeRun */ 65000 ); 65001 } 65002 } 65003 65004 if (tView.firstUpdatePass === true) { 65005 // We need to make sure that we only flip the flag on successful `refreshView` only 65006 // Don't do this in `finally` block. 65007 // If we did this in `finally` block then an exception could block the execution of styling 65008 // instructions which in turn would be unable to insert themselves into the styling linked 65009 // list. The result of this would be that if the exception would not be throw on subsequent CD 65010 // the styling would be unable to process it data and reflect to the DOM. 65011 tView.firstUpdatePass = false; 65012 } // Do not reset the dirty state when running in check no changes mode. We don't want components 65013 // to behave differently depending on whether check no changes is enabled or not. For example: 65014 // Marking an OnPush component as dirty from within the `ngAfterViewInit` hook in order to 65015 // refresh a `NgClass` binding should work. If we would reset the dirty state in the check 65016 // no changes cycle, the component would be not be dirty for the next update pass. This would 65017 // be different in production mode where the component dirty state is not reset. 65018 65019 65020 if (!isInCheckNoChangesPass) { 65021 lView[FLAGS] &= ~(32 65022 /* LViewFlags.Dirty */ 65023 | 8 65024 /* LViewFlags.FirstLViewPass */ 65025 ); 65026 } 65027 65028 if (lView[FLAGS] & 512 65029 /* LViewFlags.RefreshTransplantedView */ 65030 ) { 65031 lView[FLAGS] &= ~512 65032 /* LViewFlags.RefreshTransplantedView */ 65033 ; 65034 updateTransplantedViewCount(lView[PARENT], -1); 65035 } 65036 } finally { 65037 leaveView(); 65038 } 65039} 65040 65041function executeTemplate(tView, lView, templateFn, rf, context) { 65042 const prevSelectedIndex = getSelectedIndex(); 65043 const isUpdatePhase = rf & 2 65044 /* RenderFlags.Update */ 65045 ; 65046 65047 try { 65048 setSelectedIndex(-1); 65049 65050 if (isUpdatePhase && lView.length > HEADER_OFFSET) { 65051 // When we're updating, inherently select 0 so we don't 65052 // have to generate that instruction for most update blocks. 65053 selectIndexInternal(tView, lView, HEADER_OFFSET, !!ngDevMode && isInCheckNoChangesMode()); 65054 } 65055 65056 const preHookType = isUpdatePhase ? 2 65057 /* ProfilerEvent.TemplateUpdateStart */ 65058 : 0 65059 /* ProfilerEvent.TemplateCreateStart */ 65060 ; 65061 profiler(preHookType, context); 65062 templateFn(rf, context); 65063 } finally { 65064 setSelectedIndex(prevSelectedIndex); 65065 const postHookType = isUpdatePhase ? 3 65066 /* ProfilerEvent.TemplateUpdateEnd */ 65067 : 1 65068 /* ProfilerEvent.TemplateCreateEnd */ 65069 ; 65070 profiler(postHookType, context); 65071 } 65072} ////////////////////////// 65073//// Element 65074////////////////////////// 65075 65076 65077function executeContentQueries(tView, tNode, lView) { 65078 if (isContentQueryHost(tNode)) { 65079 const start = tNode.directiveStart; 65080 const end = tNode.directiveEnd; 65081 65082 for (let directiveIndex = start; directiveIndex < end; directiveIndex++) { 65083 const def = tView.data[directiveIndex]; 65084 65085 if (def.contentQueries) { 65086 def.contentQueries(1 65087 /* RenderFlags.Create */ 65088 , lView[directiveIndex], directiveIndex); 65089 } 65090 } 65091 } 65092} 65093/** 65094 * Creates directive instances. 65095 */ 65096 65097 65098function createDirectivesInstances(tView, lView, tNode) { 65099 if (!getBindingsEnabled()) return; 65100 instantiateAllDirectives(tView, lView, tNode, getNativeByTNode(tNode, lView)); 65101 65102 if ((tNode.flags & 128 65103 /* TNodeFlags.hasHostBindings */ 65104 ) === 128 65105 /* TNodeFlags.hasHostBindings */ 65106 ) { 65107 invokeDirectivesHostBindings(tView, lView, tNode); 65108 } 65109} 65110/** 65111 * Takes a list of local names and indices and pushes the resolved local variable values 65112 * to LView in the same order as they are loaded in the template with load(). 65113 */ 65114 65115 65116function saveResolvedLocalsInData(viewData, tNode, localRefExtractor = getNativeByTNode) { 65117 const localNames = tNode.localNames; 65118 65119 if (localNames !== null) { 65120 let localIndex = tNode.index + 1; 65121 65122 for (let i = 0; i < localNames.length; i += 2) { 65123 const index = localNames[i + 1]; 65124 const value = index === -1 ? localRefExtractor(tNode, viewData) : viewData[index]; 65125 viewData[localIndex++] = value; 65126 } 65127 } 65128} 65129/** 65130 * Gets TView from a template function or creates a new TView 65131 * if it doesn't already exist. 65132 * 65133 * @param def ComponentDef 65134 * @returns TView 65135 */ 65136 65137 65138function getOrCreateComponentTView(def) { 65139 const tView = def.tView; // Create a TView if there isn't one, or recreate it if the first create pass didn't 65140 // complete successfully since we can't know for sure whether it's in a usable shape. 65141 65142 if (tView === null || tView.incompleteFirstPass) { 65143 // Declaration node here is null since this function is called when we dynamically create a 65144 // component and hence there is no declaration. 65145 const declTNode = null; 65146 return def.tView = createTView(1 65147 /* TViewType.Component */ 65148 , declTNode, def.template, def.decls, def.vars, def.directiveDefs, def.pipeDefs, def.viewQuery, def.schemas, def.consts); 65149 } 65150 65151 return tView; 65152} 65153/** 65154 * Creates a TView instance 65155 * 65156 * @param type Type of `TView`. 65157 * @param declTNode Declaration location of this `TView`. 65158 * @param templateFn Template function 65159 * @param decls The number of nodes, local refs, and pipes in this template 65160 * @param directives Registry of directives for this view 65161 * @param pipes Registry of pipes for this view 65162 * @param viewQuery View queries for this view 65163 * @param schemas Schemas for this view 65164 * @param consts Constants for this view 65165 */ 65166 65167 65168function createTView(type, declTNode, templateFn, decls, vars, directives, pipes, viewQuery, schemas, constsOrFactory) { 65169 ngDevMode && ngDevMode.tView++; 65170 const bindingStartIndex = HEADER_OFFSET + decls; // This length does not yet contain host bindings from child directives because at this point, 65171 // we don't know which directives are active on this template. As soon as a directive is matched 65172 // that has a host binding, we will update the blueprint with that def's hostVars count. 65173 65174 const initialViewLength = bindingStartIndex + vars; 65175 const blueprint = createViewBlueprint(bindingStartIndex, initialViewLength); 65176 const consts = typeof constsOrFactory === 'function' ? constsOrFactory() : constsOrFactory; 65177 const tView = blueprint[TVIEW] = ngDevMode ? new TViewConstructor(type, // type: TViewType, 65178 blueprint, // blueprint: LView, 65179 templateFn, // template: ComponentTemplate<{}>|null, 65180 null, // queries: TQueries|null 65181 viewQuery, // viewQuery: ViewQueriesFunction<{}>|null, 65182 declTNode, // declTNode: TNode|null, 65183 cloneToTViewData(blueprint).fill(null, bindingStartIndex), // data: TData,
65184 bindingStartIndex, // bindingStartIndex: number, 65185 initialViewLength, // expandoStartIndex: number, 65186 null, // hostBindingOpCodes: HostBindingOpCodes, 65187 true, // firstCreatePass: boolean, 65188 true, // firstUpdatePass: boolean, 65189 false, // staticViewQueries: boolean, 65190 false, // staticContentQueries: boolean, 65191 null, // preOrderHooks: HookData|null, 65192 null, // preOrderCheckHooks: HookData|null, 65193 null, // contentHooks: HookData|null, 65194 null, // contentCheckHooks: HookData|null, 65195 null, // viewHooks: HookData|null, 65196 null, // viewCheckHooks: HookData|null, 65197 null, // destroyHooks: DestroyHookData|null, 65198 null, // cleanup: any[]|null, 65199 null, // contentQueries: number[]|null, 65200 null, // components: number[]|null, 65201 typeof directives === 'function' ? // 65202 directives() : // 65203 directives, // directiveRegistry: DirectiveDefList|null, 65204 typeof pipes === 'function' ? pipes() : pipes, // pipeRegistry: PipeDefList|null, 65205 null, // firstChild: TNode|null, 65206 schemas, // schemas: SchemaMetadata[]|null, 65207 consts, // consts: TConstants|null 65208 false, // incompleteFirstPass: boolean 65209 decls, // ngDevMode only: decls 65210 vars) : { 65211 type: type, 65212 blueprint: blueprint, 65213 template: templateFn, 65214 queries: null, 65215 viewQuery: viewQuery, 65216 declTNode: declTNode, 65217 data: blueprint.slice().fill(null, bindingStartIndex), 65218 bindingStartIndex: bindingStartIndex, 65219 expandoStartIndex: initialViewLength, 65220 hostBindingOpCodes: null, 65221 firstCreatePass: true, 65222 firstUpdatePass: true, 65223 staticViewQueries: false, 65224 staticContentQueries: false, 65225 preOrderHooks: null, 65226 preOrderCheckHooks: null, 65227 contentHooks: null, 65228 contentCheckHooks: null, 65229 viewHooks: null, 65230 viewCheckHooks: null, 65231 destroyHooks: null, 65232 cleanup: null, 65233 contentQueries: null, 65234 components: null, 65235 directiveRegistry: typeof directives === 'function' ? directives() : directives, 65236 pipeRegistry: typeof pipes === 'function' ? pipes() : pipes, 65237 firstChild: null, 65238 schemas: schemas, 65239 consts: consts, 65240 incompleteFirstPass: false 65241 }; 65242 65243 if (ngDevMode) { 65244 // For performance reasons it is important that the tView retains the same shape during runtime. 65245 // (To make sure that all of the code is monomorphic.) For this reason we seal the object to 65246 // prevent class transitions. 65247 Object.seal(tView); 65248 } 65249 65250 return tView; 65251} 65252 65253function createViewBlueprint(bindingStartIndex, initialViewLength) { 65254 const blueprint = ngDevMode ? new LViewBlueprint() : []; 65255 65256 for (let i = 0; i < initialViewLength; i++) { 65257 blueprint.push(i < bindingStartIndex ? null : NO_CHANGE); 65258 } 65259 65260 return blueprint; 65261} 65262 65263function createError(text, token) { 65264 return new Error(`Renderer: ${text} [${stringifyForError(token)}]`); 65265} 65266/** 65267 * Locates the host native element, used for bootstrapping existing nodes into rendering pipeline. 65268 * 65269 * @param rendererFactory Factory function to create renderer instance. 65270 * @param elementOrSelector Render element or CSS selector to locate the element. 65271 * @param encapsulation View Encapsulation defined for component that requests host element. 65272 */ 65273 65274 65275function locateHostElement(renderer, elementOrSelector, encapsulation) { 65276 // When using native Shadow DOM, do not clear host element to allow native slot projection 65277 const preserveContent = encapsulation === ViewEncapsulation$1.ShadowDom; 65278 return renderer.selectRootElement(elementOrSelector, preserveContent); 65279} 65280/** 65281 * Saves context for this cleanup function in LView.cleanupInstances. 65282 * 65283 * On the first template pass, saves in TView: 65284 * - Cleanup function 65285 * - Index of context we just saved in LView.cleanupInstances 65286 * 65287 * This function can also be used to store instance specific cleanup fns. In that case the `context` 65288 * is `null` and the function is store in `LView` (rather than it `TView`). 65289 */ 65290 65291 65292function storeCleanupWithContext(tView, lView, context, cleanupFn) { 65293 const lCleanup = getOrCreateLViewCleanup(lView); 65294 65295 if (context === null) { 65296 // If context is null that this is instance specific callback. These callbacks can only be 65297 // inserted after template shared instances. For this reason in ngDevMode we freeze the TView. 65298 if (ngDevMode) { 65299 Object.freeze(getOrCreateTViewCleanup(tView)); 65300 } 65301 65302 lCleanup.push(cleanupFn); 65303 } else { 65304 lCleanup.push(context); 65305 65306 if (tView.firstCreatePass) { 65307 getOrCreateTViewCleanup(tView).push(cleanupFn, lCleanup.length - 1); 65308 } 65309 } 65310} 65311 65312function createTNode(tView, tParent, type, index, value, attrs) { 65313 ngDevMode && index !== 0 && // 0 are bogus nodes and they are OK. See `createContainerRef` in 65314 // `view_engine_compatibility` for additional context. 65315 assertGreaterThanOrEqual(index, HEADER_OFFSET, 'TNodes can\'t be in the LView header.'); 65316 ngDevMode && assertNotSame(attrs, undefined, '\'undefined\' is not val
65316id value for \'attrs\''); 65317 ngDevMode && ngDevMode.tNode++; 65318 ngDevMode && tParent && assertTNodeForTView(tParent, tView); 65319 let injectorIndex = tParent ? tParent.injectorIndex : -1; 65320 const tNode = ngDevMode ? new TNodeDebug(tView, // tView_: TView 65321 type, // type: TNodeType 65322 index, // index: number 65323 null, // insertBeforeIndex: null|-1|number|number[] 65324 injectorIndex, // injectorIndex: number 65325 -1, // directiveStart: number 65326 -1, // directiveEnd: number 65327 -1, // directiveStylingLast: number 65328 null, // propertyBindings: number[]|null 65329 0, // flags: TNodeFlags 65330 0, // providerIndexes: TNodeProviderIndexes 65331 value, // value: string|null 65332 attrs, // attrs: (string|AttributeMarker|(string|SelectorFlags)[])[]|null 65333 null, // mergedAttrs 65334 null, // localNames: (string|number)[]|null 65335 undefined, // initialInputs: (string[]|null)[]|null|undefined 65336 null, // inputs: PropertyAliases|null 65337 null, // outputs: PropertyAliases|null 65338 null, // tViews: ITView|ITView[]|null 65339 null, // next: ITNode|null 65340 null, // projectionNext: ITNode|null 65341 null, // child: ITNode|null 65342 tParent, // parent: TElementNode|TContainerNode|null 65343 null, // projection: number|(ITNode|RNode[])[]|null 65344 null, // styles: string|null 65345 null, // stylesWithoutHost: string|null 65346 undefined, // residualStyles: string|null 65347 null, // classes: string|null 65348 null, // classesWithoutHost: string|null 65349 undefined, // residualClasses: string|null 65350 0, // classBindings: TStylingRange; 65351 0) : { 65352 type, 65353 index, 65354 insertBeforeIndex: null, 65355 injectorIndex, 65356 directiveStart: -1, 65357 directiveEnd: -1, 65358 directiveStylingLast: -1, 65359 propertyBindings: null, 65360 flags: 0, 65361 providerIndexes: 0, 65362 value: value, 65363 attrs: attrs, 65364 mergedAttrs: null, 65365 localNames: null, 65366 initialInputs: undefined, 65367 inputs: null, 65368 outputs: null, 65369 tViews: null, 65370 next: null, 65371 projectionNext: null, 65372 child: null, 65373 parent: tParent, 65374 projection: null, 65375 styles: null, 65376 stylesWithoutHost: null, 65377 residualStyles: undefined, 65378 classes: null, 65379 classesWithoutHost: null, 65380 residualClasses: undefined, 65381 classBindings: 0, 65382 styleBindings: 0 65383 }; 65384 65385 if (ngDevMode) { 65386 // For performance reasons it is important that the tNode retains the same shape during runtime. 65387 // (To make sure that all of the code is monomorphic.) For this reason we seal the object to 65388 // prevent class transitions. 65389 Object.seal(tNode); 65390 } 65391 65392 return tNode; 65393} 65394 65395function generatePropertyAliases(inputAliasMap, directiveDefIdx, propStore) { 65396 for (let publicName in inputAliasMap) { 65397 if (inputAliasMap.hasOwnProperty(publicName)) { 65398 propStore = propStore === null ? {} : propStore; 65399 const internalName = inputAliasMap[publicName]; 65400 65401 if (propStore.hasOwnProperty(publicName)) { 65402 propStore[publicName].push(directiveDefIdx, internalName); 65403 } else { 65404 propStore[publicName] = [directiveDefIdx, internalName]; 65405 } 65406 } 65407 } 65408 65409 return propStore; 65410} 65411/** 65412 * Initializes data structures required to work with directive inputs and outputs. 65413 * Initialization is done for all directives matched on a given TNode. 65414 */ 65415 65416 65417function initializeInputAndOutputAliases(tView, tNode) { 65418 ngDevMode && assertFirstCreatePass(tView); 65419 const start = tNode.directiveStart; 65420 const end = tNode.directiveEnd; 65421 const tViewData = tView.data; 65422 const tNodeAttrs = tNode.attrs; 65423 const inputsFromAttrs = ngDevMode ? new TNodeInitialInputs() : []; 65424 let inputsStore = null; 65425 let outputsStore = null; 65426 65427 for (let i = start; i < end; i++) { 65428 const directiveDef = tViewData[i]; 65429 const directiveInputs = directiveDef.inputs; // Do not use unbound attributes as inputs to structural directives, since structural 65430 // directive inputs can only be set using microsyntax (e.g. `<div *dir="exp">`). 65431 // TODO(FW-1930): microsyntax expressions may also contain unbound/static attributes, which 65432 // should be set for inline templates. 65433 65434 const initialInputs = tNodeAttrs !== null && !isInlineTemplate(tNode) ? generateInitialInputs(directiveInputs, tNodeAttrs) : null; 65435 inputsFromAttrs.push(initialInputs); 65436 inputsStore = generatePropertyAliases(directiveInputs, i, inputsStore); 65437 outputsStore = generatePropertyAliases(directiveDef.outputs, i, outputsStore); 65438 } 65439 65440 if (inputsStore !== null) { 65441 if (inputsStore.hasOwnProperty('class')) { 65442 tNode.flags |= 16 65443 /* TNodeFlags.hasClassInput */ 65444 ; 65445 } 65446 65447 if (inputsStore.hasOwnProperty('style')) { 65448 tNode.flags |= 32 65449 /* TNodeFlags.hasStyleInput */ 65450 ; 65451 } 65452 } 65453
vendor: 12,372 bytes, lines 65454-65814
65454 tNode.initialInputs = inputsFromAttrs; 65455 tNode.inputs = inputsStore; 65456 tNode.outputs = outputsStore; 65457} 65458/** 65459 * Mapping between attributes names that don't correspond to their element property names. 65460 * 65461 * Performance note: this function is written as a series of if checks (instead of, say, a property 65462 * object lookup) for performance reasons - the series of `if` checks seems to be the fastest way of 65463 * mapping property names. Do NOT change without benchmarking. 65464 * 65465 * Note: this mapping has to be kept in sync with the equally named mapping in the template 65466 * type-checking machinery of ngtsc. 65467 */ 65468 65469 65470function mapPropName(name) { 65471 if (name === 'class') return 'className'; 65472 if (name === 'for') return 'htmlFor'; 65473 if (name === 'formaction') return 'formAction'; 65474 if (name === 'innerHtml') return 'innerHTML'; 65475 if (name === 'readonly') return 'readOnly'; 65476 if (name === 'tabindex') return 'tabIndex'; 65477 return name; 65478} 65479 65480function elementPropertyInternal(tView, tNode, lView, propName, value, renderer, sanitizer, nativeOnly) { 65481 ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.'); 65482 const element = getNativeByTNode(tNode, lView); 65483 let inputData = tNode.inputs; 65484 let dataValue; 65485 65486 if (!nativeOnly && inputData != null && (dataValue = inputData[propName])) { 65487 setInputsForProperty(tView, lView, dataValue, propName, value); 65488 if (isComponentHost(tNode)) markDirtyIfOnPush(lView, tNode.index); 65489 65490 if (ngDevMode) { 65491 setNgReflectProperties(lView, element, tNode.type, dataValue, value); 65492 } 65493 } else if (tNode.type & 3 65494 /* TNodeType.AnyRNode */ 65495 ) { 65496 propName = mapPropName(propName); 65497 65498 if (ngDevMode) { 65499 validateAgainstEventProperties(propName); 65500 65501 if (!isPropertyValid(element, propName, tNode.value, tView.schemas)) { 65502 handleUnknownPropertyError(propName, tNode.value, tNode.type, lView); 65503 } 65504 65505 ngDevMode.rendererSetProperty++; 65506 } // It is assumed that the sanitizer is only added when the compiler determines that the 65507 // property is risky, so sanitization can be done without further checks. 65508 65509 65510 value = sanitizer != null ? sanitizer(value, tNode.value || '', propName) : value; 65511 renderer.setProperty(element, propName, value); 65512 } else if (tNode.type & 12 65513 /* TNodeType.AnyContainer */ 65514 ) { 65515 // If the node is a container and the property didn't 65516 // match any of the inputs or schemas we should throw. 65517 if (ngDevMode && !matchingSchemas(tView.schemas, tNode.value)) { 65518 handleUnknownPropertyError(propName, tNode.value, tNode.type, lView); 65519 } 65520 } 65521} 65522/** If node is an OnPush component, marks its LView dirty. */ 65523 65524 65525function markDirtyIfOnPush(lView, viewIndex) { 65526 ngDevMode && assertLView(lView); 65527 const childComponentLView = getComponentLViewByIndex(viewIndex, lView); 65528 65529 if (!(childComponentLView[FLAGS] & 16 65530 /* LViewFlags.CheckAlways */ 65531 )) { 65532 childComponentLView[FLAGS] |= 32 65533 /* LViewFlags.Dirty */ 65534 ; 65535 } 65536} 65537 65538function setNgReflectProperty(lView, element, type, attrName, value) { 65539 const renderer = lView[RENDERER]; 65540 attrName = normalizeDebugBindingName(attrName); 65541 const debugValue = normalizeDebugBindingValue(value); 65542 65543 if (type & 3 65544 /* TNodeType.AnyRNode */ 65545 ) { 65546 if (value == null) { 65547 renderer.removeAttribute(element, attrName); 65548 } else { 65549 renderer.setAttribute(element, attrName, debugValue); 65550 } 65551 } else { 65552 const textContent = escapeCommentText(`bindings=${JSON.stringify({ 65553 [attrName]: debugValue 65554 }, null, 2)}`); 65555 renderer.setValue(element, textContent); 65556 } 65557} 65558 65559function setNgReflectProperties(lView, element, type, dataValue, value) { 65560 if (type & (3 65561 /* TNodeType.AnyRNode */ 65562 | 4 65563 /* TNodeType.Container */ 65564 )) { 65565 /** 65566 * dataValue is an array containing runtime input or output names for the directives: 65567 * i+0: directive instance index 65568 * i+1: privateName 65569 * 65570 * e.g. [0, 'change', 'change-minified'] 65571 * we want to set the reflected property with the privateName: dataValue[i+1] 65572 */ 65573 for (let i = 0; i < dataValue.length; i += 2) { 65574 setNgReflectProperty(lView, element, type, dataValue[i + 1], value); 65575 } 65576 } 65577} 65578/** 65579 * Instantiate a root component. 65580 */ 65581 65582 65583function instantiateRootComponent(tView, lView, def) { 65584 const rootTNode = getCurrentTNode(); 65585 65586 if (tView.firstCreatePass) { 65587 if (def.providersResolver) def.providersResolver(def); 65588 const directiveIndex = allocExpando(tView, lView, 1, null); 65589 ngDevMode && assertEqual(directiveIndex, rootTNode.directiveStart, 'Because this is a root component the allocated expando should match the TNode component.'); 65590 configureViewWithDirective(tView, rootTNode, lView, directiveIndex, def); 65591 initializeInputAndOutputAliases(tView, rootTNode); 65592 } 65593 65594 const directive = getNodeInjectable(lView, tView, rootTNode.directiveStart, rootTNode); 65595 attachPatchData(directive, lView); 65596 const native = getNativeByTNode(rootTNode, lView); 65597 65598 if (native) { 65599 attachPatchData(native, lView); 65600 } 65601 65602 return directive; 65603} 65604/** 65605 * Resolve the matched directives on a node. 65606 */ 65607 65608 65609function resolveDirectives(tView, lView, tNode, localRefs) { 65610 // Please make sure to have explicit type for `exportsMap`. Inferred type triggers bug in 65611 // tsickle. 65612 ngDevMode && assertFirstCreatePass(tView); 65613 let hasDirectives = false; 65614 65615 if (getBindingsEnabled()) { 65616 const directiveDefs = findDirectiveDefMatches(tView, lView, tNode); 65617 const exportsMap = localRefs === null ? null : { 65618 '': -1 65619 }; 65620 65621 if (directiveDefs !== null) { 65622 hasDirectives = true; 65623 initTNodeFlags(tNode, tView.data.length, directiveDefs.length); // When the same token is provided by several directives on the same node, some rules apply in 65624 // the viewEngine: 65625 // - viewProviders have priority over providers 65626 // - the last directive in NgModule.declarations has priority over the previous one 65627 // So to match these rules, the order in which providers are added in the arrays is very 65628 // important. 65629 65630 for (let i = 0; i < directiveDefs.length; i++) { 65631 const def = directiveDefs[i]; 65632 if (def.providersResolver) def.providersResolver(def); 65633 } 65634 65635 let preOrderHooksFound = false; 65636 let preOrderCheckHooksFound = false; 65637 let directiveIdx = allocExpando(tView, lView, directiveDefs.length, null); 65638 ngDevMode && assertSame(directiveIdx, tNode.directiveStart, 'TNode.directiveStart should point to just allocated space'); 65639 65640 for (let i = 0; i < directiveDefs.length; i++) { 65641 const def = directiveDefs[i]; // Merge the attrs in the order of matches. This assumes that the first directive is the 65642 // component itself, so that the component has the least priority. 65643 65644 tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, def.hostAttrs); 65645 configureViewWithDirective(tView, tNode, lView, directiveIdx, def); 65646 saveNameToExportMap(directiveIdx, def, exportsMap); 65647 if (def.contentQueries !== null) tNode.flags |= 8 65648 /* TNodeFlags.hasContentQuery */ 65649 ; 65650 if (def.hostBindings !== null || def.hostAttrs !== null || def.hostVars !== 0) tNode.flags |= 128 65651 /* TNodeFlags.hasHostBindings */ 65652 ; 65653 const lifeCycleHooks = def.type.prototype; // Only push a node index into the preOrderHooks array if this is the first 65654 // pre-order hook found on this node. 65655 65656 if (!preOrderHooksFound && (lifeCycleHooks.ngOnChanges || lifeCycleHooks.ngOnInit || lifeCycleHooks.ngDoCheck)) { 65657 // We will push the actual hook function into this array later during dir instantiation. 65658 // We cannot do it now because we must ensure hooks are registered in the same 65659 // order that directives are created (i.e. injection order). 65660 (tView.preOrderHooks || (tView.preOrderHooks = [])).push(tNode.index); 65661 preOrderHooksFound = true; 65662 } 65663 65664 if (!preOrderCheckHooksFound && (lifeCycleHooks.ngOnChanges || lifeCycleHooks.ngDoCheck)) { 65665 (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = [])).push(tNode.index); 65666 preOrderCheckHooksFound = true; 65667 } 65668 65669 directiveIdx++; 65670 } 65671 65672 initializeInputAndOutputAliases(tView, tNode); 65673 } 65674 65675 if (exportsMap) cacheMatchingLocalNames(tNode, localRefs, exportsMap); 65676 } // Merge the template attrs last so that they have the highest priority. 65677 65678 65679 tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, tNode.attrs); 65680 return hasDirectives; 65681} 65682/** 65683 * Add `hostBindings` to the `TView.hostBindingOpCodes`. 65684 * 65685 * @param tView `TView` to which the `hostBindings` should be added. 65686 * @param tNode `TNode` the element which contains the directive 65687 * @param lView `LView` current `LView` 65688 * @param directiveIdx Directive index in view. 65689 * @param directiveVarsIdx Where will the directive's vars be stored 65690 * @param def `ComponentDef`/`DirectiveDef`, which contains the `hostVars`/`hostBindings` to add. 65691 */ 65692 65693 65694function registerHostBindingOpCodes(tView, tNode, lView, directiveIdx, directiveVarsIdx, def) { 65695 ngDevMode && assertFirstCreatePass(tView); 65696 const hostBindings = def.hostBindings; 65697 65698 if (hostBindings) { 65699 let hostBindingOpCodes = tView.hostBindingOpCodes; 65700 65701 if (hostBindingOpCodes === null) { 65702 hostBindingOpCodes = tView.hostBindingOpCodes = []; 65703 } 65704 65705 const elementIndx = ~tNode.index; 65706 65707 if (lastSelectedElementIdx(hostBindingOpCodes) != elementIndx) { 65708 // Conditionally add select element so that we are more efficient in execution. 65709 // NOTE: this is strictly not necessary and it trades code size for runtime perf. 65710 // (We could just always add it.) 65711 hostBindingOpCodes.push(elementIndx); 65712 } 65713 65714 hostBindingOpCodes.push(directiveIdx, directiveVarsIdx, hostBindings); 65715 } 65716} 65717/** 65718 * Returns the last selected element index in the `HostBindingOpCodes` 65719 * 65720 * For perf reasons we don't need to update the selected element index in `HostBindingOpCodes` only 65721 * if it changes. This method returns the last index (or '0' if not found.) 65722 * 65723 * Selected element index are only the ones which are negative. 65724 */ 65725 65726 65727function lastSelectedElementIdx(hostBindingOpCodes) { 65728 let i = hostBindingOpCodes.length; 65729 65730 while (i > 0) { 65731 const value = hostBindingOpCodes[--i]; 65732 65733 if (typeof value === 'number' && value < 0) { 65734 return value; 65735 } 65736 } 65737 65738 return 0; 65739} 65740/** 65741 * Instantiate all the directives that were previously resolved on the current node. 65742 */ 65743 65744 65745function instantiateAllDirectives(tView, lView, tNode, native) { 65746 const start = tNode.directiveStart; 65747 const end = tNode.directiveEnd; 65748 65749 if (!tView.firstCreatePass) { 65750 getOrCreateNodeInjectorForNode(tNode, lView); 65751 } 65752 65753 attachPatchData(native, lView); 65754 const initialInputs = tNode.initialInputs; 65755 65756 for (let i = start; i < end; i++) { 65757 const def = tView.data[i]; 65758 const isComponent = isComponentDef(def); 65759 65760 if (isComponent) { 65761 ngDevMode && assertTNodeType(tNode, 3 65762 /* TNodeType.AnyRNode */ 65763 ); 65764 addComponentLogic(lView, tNode, def); 65765 } 65766 65767 const directive = getNodeInjectable(lView, tView, i, tNode); 65768 attachPatchData(directive, lView); 65769 65770 if (initialInputs !== null) { 65771 setInputsFromAttrs(lView, i - start, directive, def, tNode, initialInputs); 65772 } 65773 65774 if (isComponent) { 65775 const componentView = getComponentLViewByIndex(tNode.index, lView); 65776 componentView[CONTEXT] = directive; 65777 } 65778 } 65779} 65780 65781function invokeDirectivesHostBindings(tView, lView, tNode) { 65782 const start = tNode.directiveStart; 65783 const end = tNode.directiveEnd; 65784 const elementIndex = tNode.index; 65785 const currentDirectiveIndex = getCurrentDirectiveIndex(); 65786 65787 try { 65788 setSelectedIndex(elementIndex); 65789 65790 for (let dirIndex = start; dirIndex < end; dirIndex++) { 65791 const def = tView.data[dirIndex]; 65792 const directive = lView[dirIndex]; 65793 setCurrentDirectiveIndex(dirIndex); 65794 65795 if (def.hostBindings !== null || def.hostVars !== 0 || def.hostAttrs !== null) { 65796 invokeHostBindingsInCreationMode(def, directive); 65797 } 65798 } 65799 } finally { 65800 setSelectedIndex(-1); 65801 setCurrentDirectiveIndex(currentDirectiveIndex); 65802 } 65803} 65804/** 65805 * Invoke the host bindings in creation mode. 65806 * 65807 * @param def `DirectiveDef` which may contain the `hostBindings` function. 65808 * @param directive Instance of directive. 65809 */ 65810 65811 65812function invokeHostBindingsInCreationMode(def, directive) { 65813 if (def.hostBindings !== null) { 65814 def.hostBindings(1
65815 /* RenderFlags.Create */ 65816 , directive); 65817 } 65818} 65819/** 65820 * Matches the current node against all available selectors. 65821 * If a component is matched (at most one), it is returned in first position in the array. 65822 */ 65823 65824 65825function findDirectiveDefMatches(tView, viewData, tNode) { 65826 ngDevMode && assertFirstCreatePass(tView); 65827 ngDevMode && assertTNodeType(tNode, 3 65828 /* TNodeType.AnyRNode */ 65829 | 12 65830 /* TNodeType.AnyContainer */ 65831 ); 65832 const registry = tView.directiveRegistry; 65833 let matches = null; 65834 65835 if (registry) { 65836 for (let i = 0; i < registry.length; i++) { 65837 const def = registry[i]; 65838 65839 if (isNodeMatchingSelectorList(tNode, def.selectors, 65840 /* isProjectionMode */ 65841 false)) { 65842 matches || (matches = ngDevMode ? new MatchesArray() : []); 65843 diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, viewData), tView, def.type); 65844 65845 if (isComponentDef(def)) { 65846 if (ngDevMode) { 65847 assertTNodeType(tNode, 2 65848 /* TNodeType.Element */ 65849 , `"${tNode.value}" tags cannot be used as component hosts. ` + `Please use a different tag to activate the ${stringify(def.type)} component.`); 65850 65851 if (tNode.flags & 2 65852 /* TNodeFlags.isComponentHost */ 65853 ) { 65854 // If another component has been matched previously, it's the first element in the 65855 // `matches` array, see how we store components/directives in `matches` below. 65856 throwMultipleComponentError(tNode, matches[0].type, def.type); 65857 } 65858 } 65859 65860 markAsComponentHost(tView, tNode); // The component is always stored first with directives after. 65861 65862 matches.unshift(def); 65863 } else { 65864 matches.push(def); 65865 } 65866 } 65867 } 65868 } 65869 65870 return matches; 65871} 65872/** 65873 * Marks a given TNode as a component's host. This consists of: 65874 * - setting appropriate TNode flags; 65875 * - storing index of component's host element so it will be queued for view refresh during CD. 65876 */ 65877 65878 65879function markAsComponentHost(tView, hostTNode) { 65880 ngDevMode && assertFirstCreatePass(tView); 65881 hostTNode.flags |= 2 65882 /* TNodeFlags.isComponentHost */ 65883 ; 65884 (tView.components || (tView.components = ngDevMode ? new TViewComponents() : [])).push(hostTNode.index); 65885} 65886/** Caches local names and their matching directive indices for query and template lookups. */ 65887 65888 65889function cacheMatchingLocalNames(tNode, localRefs, exportsMap) { 65890 if (localRefs) { 65891 const localNames = tNode.localNames = ngDevMode ? new TNodeLocalNames() : []; // Local names must be stored in tNode in the same order that localRefs are defined 65892 // in the template to ensure the data is loaded in the same slots as their refs 65893 // in the template (for template queries). 65894 65895 for (let i = 0; i < localRefs.length; i += 2) { 65896 const index = exportsMap[localRefs[i + 1]]; 65897 if (index == null) throw new RuntimeError(-301 65898 /* RuntimeErrorCode.EXPORT_NOT_FOUND */ 65899 , ngDevMode && `Export of name '${localRefs[i + 1]}' not found!`); 65900 localNames.push(localRefs[i], index); 65901 } 65902 } 65903} 65904/** 65905 * Builds up an export map as directives are created, so local refs can be quickly mapped 65906 * to their directive instances. 65907 */ 65908 65909 65910function saveNameToExportMap(directiveIdx, def, exportsMap) { 65911 if (exportsMap) { 65912 if (def.exportAs) { 65913 for (let i = 0; i < def.exportAs.length; i++) { 65914 exportsMap[def.exportAs[i]] = directiveIdx; 65915 } 65916 } 65917 65918 if (isComponentDef(def)) exportsMap[''] = directiveIdx; 65919 } 65920} 65921/** 65922 * Initializes the flags on the current node, setting all indices to the initial index, 65923 * the directive count to 0, and adding the isComponent flag. 65924 * @param index the initial index 65925 */ 65926 65927 65928function initTNodeFlags(tNode, index, numberOfDirectives) { 65929 ngDevMode && assertNotEqual(numberOfDirectives, tNode.directiveEnd - tNode.directiveStart, 'Reached the max number of directives'); 65930 tNode.flags |= 1 65931 /* TNodeFlags.isDirectiveHost */ 65932 ; // When the first directive is created on a node, save the index 65933 65934 tNode.directiveStart = index; 65935 tNode.directiveEnd = index + numberOfDirectives; 65936 tNode.providerIndexes = index; 65937} 65938/** 65939 * Setup directive for instantiation. 65940 * 65941 * We need to create a `NodeInjectorFactory` which is then inserted in both the `Blueprint` as well 65942 * as `LView`. `TView` gets the `DirectiveDef`. 65943 * 65944 * @param tView `TView` 65945 * @param tNode `TNode` 65946 * @param lView `LView` 65947 * @param directiveIndex Index where the directive will be stored in the Expando. 65948 * @param def `DirectiveDef` 65949 */ 65950 65951 65952function configureViewWithDirective(tView, tNode, lView, directiveIndex, def) { 65953 ngDevMode && assertGreaterThanOrEqual(directiveIndex, HEADER_OFFSET, 'Must be in Expando section'); 65954 tView.data[directiveIndex] = def; 65955 const directiveFactory = def.factory || (def.factory = getFactoryDef(def.type, true)); // Even though `directiveFactory` will already be using `ɵɵdirectiveInject` in its generated code,
vendor: 4,739 bytes, lines 65956-66074
65956 // we also want to support `inject()` directly from the directive constructor context so we set 65957 // `ɵɵdirectiveInject` as the inject implementation here too. 65958 65959 const nodeInjectorFactory = new NodeInjectorFactory(directiveFactory, isComponentDef(def), ɵɵdirectiveInject); 65960 tView.blueprint[directiveIndex] = nodeInjectorFactory; 65961 lView[directiveIndex] = nodeInjectorFactory; 65962 registerHostBindingOpCodes(tView, tNode, lView, directiveIndex, allocExpando(tView, lView, def.hostVars, NO_CHANGE), def); 65963} 65964 65965function addComponentLogic(lView, hostTNode, def) { 65966 const native = getNativeByTNode(hostTNode, lView); 65967 const tView = getOrCreateComponentTView(def); // Only component views should be added to the view tree directly. Embedded views are 65968 // accessed through their containers because they may be removed / re-added later. 65969 65970 const rendererFactory = lView[RENDERER_FACTORY]; 65971 const componentView = addToViewTree(lView, createLView(lView, tView, null, def.onPush ? 32 65972 /* LViewFlags.Dirty */ 65973 : 16 65974 /* LViewFlags.CheckAlways */ 65975 , native, hostTNode, rendererFactory, rendererFactory.createRenderer(native, def), null, null, null)); // Component view will always be created before any injected LContainers, 65976 // so this is a regular element, wrap it with the component view 65977 65978 lView[hostTNode.index] = componentView; 65979} 65980 65981function elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace) { 65982 if (ngDevMode) { 65983 assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.'); 65984 validateAgainstEventAttributes(name); 65985 assertTNodeType(tNode, 2 65986 /* TNodeType.Element */ 65987 , `Attempted to set attribute \`${name}\` on a container node. ` + `Host bindings are not valid on ng-container or ng-template.`); 65988 } 65989 65990 const element = getNativeByTNode(tNode, lView); 65991 setElementAttribute(lView[RENDERER], element, namespace, tNode.value, name, value, sanitizer); 65992} 65993 65994function setElementAttribute(renderer, element, namespace, tagName, name, value, sanitizer) { 65995 if (value == null) { 65996 ngDevMode && ngDevMode.rendererRemoveAttribute++; 65997 renderer.removeAttribute(element, name, namespace); 65998 } else { 65999 ngDevMode && ngDevMode.rendererSetAttribute++; 66000 const strValue = sanitizer == null ? renderStringify(value) : sanitizer(value, tagName || '', name); 66001 renderer.setAttribute(element, name, strValue, namespace); 66002 } 66003} 66004/** 66005 * Sets initial input properties on directive instances from attribute data 66006 * 66007 * @param lView Current LView that is being processed. 66008 * @param directiveIndex Index of the directive in directives array 66009 * @param instance Instance of the directive on which to set the initial inputs 66010 * @param def The directive def that contains the list of inputs 66011 * @param tNode The static data for this node 66012 */ 66013 66014 66015function setInputsFromAttrs(lView, directiveIndex, instance, def, tNode, initialInputData) { 66016 const initialInputs = initialInputData[directiveIndex]; 66017 66018 if (initialInputs !== null) { 66019 const setInput = def.setInput; 66020 66021 for (let i = 0; i < initialInputs.length;) { 66022 const publicName = initialInputs[i++]; 66023 const privateName = initialInputs[i++]; 66024 const value = initialInputs[i++]; 66025 66026 if (setInput !== null) { 66027 def.setInput(instance, value, publicName, privateName); 66028 } else { 66029 instance[privateName] = value; 66030 } 66031 66032 if (ngDevMode) { 66033 const nativeElement = getNativeByTNode(tNode, lView); 66034 setNgReflectProperty(lView, nativeElement, tNode.type, privateName, value); 66035 } 66036 } 66037 } 66038} 66039/** 66040 * Generates initialInputData for a node and stores it in the template's static storage 66041 * so subsequent template invocations don't have to recalculate it. 66042 * 66043 * initialInputData is an array containing values that need to be set as input properties 66044 * for directives on this node, but only once on creation. We need this array to support 66045 * the case where you set an @Input property of a directive using attribute-like syntax. 66046 * e.g. if you have a `name` @Input, you can set it once like this: 66047 * 66048 * <my-component name="Bess"></my-component> 66049 * 66050 * @param inputs The list of inputs from the directive def 66051 * @param attrs The static attrs on this node 66052 */ 66053 66054 66055function generateInitialInputs(inputs, attrs) { 66056 let inputsToStore = null; 66057 let i = 0; 66058 66059 while (i < attrs.length) { 66060 const attrName = attrs[i]; 66061 66062 if (attrName === 0 66063 /* AttributeMarker.NamespaceURI */ 66064 ) { 66065 // We do not allow inputs on namespaced attributes. 66066 i += 4; 66067 continue; 66068 } else if (attrName === 5 66069 /* AttributeMarker.ProjectAs */ 66070 ) { 66071 // Skip over the `ngProjectAs` value. 66072 i += 2; 66073 continue; 66074 } // If we hit any other attribute markers, we're done anyway. None of those are valid input
66074s. 66075 66076 66077 if (typeof attrName === 'number') break; 66078 66079 if (inputs.hasOwnProperty(attrName)) { 66080 if (inputsToStore === null) inputsToStore = []; 66081 inputsToStore.push(attrName, inputs[attrName], attrs[i + 1]); 66082 } 66083 66084 i += 2; 66085 } 66086 66087 return inputsToStore; 66088} ////////////////////////// 66089//// ViewContainer & View 66090////////////////////////// 66091// Not sure why I need to do `any` here but TS complains later. 66092 66093 66094const LContainerArray = class LContainer extends Array {}; 66095/** 66096 * Creates a LContainer, either from a container instruction, or for a ViewContainerRef. 66097 * 66098 * @param hostNative The host element for the LContainer 66099 * @param hostTNode The host TNode for the LContainer 66100 * @param currentView The parent view of the LContainer 66101 * @param native The native comment element 66102 * @param isForViewContainerRef Optional a flag indicating the ViewContainerRef case 66103 * @returns LContainer 66104 */ 66105 66106function createLContainer(hostNative, currentView, native, tNode) { 66107 ngDevMode && assertLView(currentView); // https://jsperf.com/array-literal-vs-new-array-really 66108 66109 const lContainer = new (ngDevMode ? LContainerArray : Array)(hostNative, // host native 66110 true, // Boolean `true` in this position signifies that this is an `LContainer` 66111 false, // has transplanted views 66112 currentView, // parent 66113 null, // next 66114 0, // transplanted views to refresh count 66115 tNode, // t_host 66116 native, // native, 66117 null, // view refs 66118 null); 66119 ngDevMode && assertEqual(lContainer.length, CONTAINER_HEADER_OFFSET, 'Should allocate correct number of slots for LContainer header.'); 66120 ngDevMode && attachLContainerDebug(lContainer); 66121 return lContainer; 66122} 66123/** 66124 * Goes over embedded views (ones created through ViewContainerRef APIs) and refreshes 66125 * them by executing an associated template function. 66126 */ 66127 66128 66129function refreshEmbeddedViews(lView) { 66130 for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) { 66131 for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) { 66132 const embeddedLView = lContainer[i]; 66133 const embeddedTView = embeddedLView[TVIEW]; 66134 ngDevMode && assertDefined(embeddedTView, 'TView must be allocated'); 66135 66136 if (viewAttachedToChangeDetector(embeddedLView)) { 66137 refreshView(embeddedTView, embeddedLView, embeddedTView.template, embeddedLView[CONTEXT]); 66138 } 66139 } 66140 } 66141} 66142/** 66143 * Mark transplanted views as needing to be refreshed at their insertion points. 66144 * 66145 * @param lView The `LView` that may have transplanted views. 66146 */ 66147 66148 66149function markTransplantedViewsForRefresh(lView) { 66150 for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) { 66151 if (!lContainer[HAS_TRANSPLANTED_VIEWS]) continue; 66152 const movedViews = lContainer[MOVED_VIEWS]; 66153 ngDevMode && assertDefined(movedViews, 'Transplanted View flags set but missing MOVED_VIEWS'); 66154 66155 for (let i = 0; i < movedViews.length; i++) { 66156 const movedLView = movedViews[i]; 66157 const insertionLContainer = movedLView[PARENT]; 66158 ngDevMode && assertLContainer(insertionLContainer); // We don't want to increment the counter if the moved LView was already marked for 66159 // refresh. 66160 66161 if ((movedLView[FLAGS] & 512 66162 /* LViewFlags.RefreshTransplantedView */ 66163 ) === 0) { 66164 updateTransplantedViewCount(insertionLContainer, 1); 66165 } // Note, it is possible that the `movedViews` is tracking views that are transplanted *and* 66166 // those that aren't (declaration component === insertion component). In the latter case, 66167 // it's fine to add the flag, as we will clear it immediately in 66168 // `refreshEmbeddedViews` for the view currently being refreshed. 66169 66170 66171 movedLView[FLAGS] |= 512 66172 /* LViewFlags.RefreshTransplantedView */ 66173 ; 66174 } 66175 } 66176} ///////////// 66177 66178/** 66179 * Refreshes components by entering the component view and processing its bindings, queries, etc. 66180 * 66181 * @param componentHostIdx Element index in LView[] (adjusted for HEADER_OFFSET) 66182 */ 66183 66184 66185function refreshComponent(hostLView, componentHostIdx) { 66186 ngDevMode && assertEqual(isCreationMode(hostLView), false, 'Should be run in update mode'); 66187 const componentView = getComponentLViewByIndex(componentHostIdx, hostLView); // Only attached components that are CheckAlways or OnPush and dirty should be refreshed 66188 66189 if (viewAttachedToChangeDetector(componentView)) { 66190 const tView = componentView[TVIEW]; 66191 66192 if (componentView[FLAGS] & (16 66193 /* LViewFlags.CheckAlways */ 66194 | 32 66195 /* LViewFlags.Dirty */ 66196 )) { 66197 refreshView(tView, componentView, tView.template, componentView[CONTEXT]); 66198 } else if (componentView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) { 66199 // Only attached components that are CheckAlways or OnPush and dirty should be refreshed 66200 refreshContainsDirtyView(componentView); 66201 } 66202 } 66203} 66204/** 66205 * Refreshes all transplanted views marked with `LViewFlags.RefreshTransplantedView` that are 66206 * children or descendants of the given lView. 66207 * 66208 * @param lView The lView which contains descendant transplanted views that need to be refreshed. 66209 */ 66210 66211 66212function refreshContainsDirtyView(lView) { 66213 for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) { 66214 for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) { 66215 const embeddedLView = lContainer[i]; 66216 66217 if (viewAttachedToChangeDetector(embeddedLView)) { 66218 if (embeddedLView[FLAGS] & 512 66219 /* LViewFlags.RefreshTransplantedView */ 66220 ) { 66221 const embeddedTView = embeddedLView[TVIEW]; 66222 ngDevMode && assertDefined(embeddedTView, 'TView must be allocated'); 66223 refreshView(embeddedTView, embeddedLView, embeddedTView.template, embeddedLView[CONTEXT]); 66224 } else if (embeddedLView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) { 66225 refreshContainsDirtyView(embeddedLView); 66226 } 66227 } 66228 } 66229 } 66230 66231 const tView = lView[TVIEW]; // Refresh child component views. 66232 66233 const components = tView.components; 66234 66235 if (components !== null) { 66236 for (let i = 0; i < components.length; i++) { 66237 const componentView = getComponentLViewByIndex(components[i], lView); // Only attached components that are CheckAlways or OnPush and dirty should be refreshed 66238 66239 if (viewAttachedToChangeDetector(componentView) && componentView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) { 66240 refreshContainsDirtyView(componentView); 66241 } 66242 } 66243 } 66244} 66245 66246function renderComponent(hostLView, componentHostIdx) { 66247 ngDevMode && assertEqual(isCreationMode(hostLView), true, 'Should be run in creation mode'); 66248 const componentView = getComponentLViewByIndex(componentHostIdx, hostLView); 66249 const componentTView = componentView[TVIEW]; 66250 syncViewWithBlueprint(componentTView, componentView); 66251 renderView(componentTView, componentView, componentView[CONTEXT]); 66252} 66253/** 66254 * Syncs an LView instance with its blueprint if they have gotten out of sync. 66255 * 66256 * Typically, blueprints and their view instances should always be in sync, so the loop here 66257 * will be skipped. However, consider this case of two components side-by-side: 66258 * 66259 * App template: 66260 * ``` 66261 * <comp></comp> 66262 * <comp></comp> 66263 * ``` 66264 * 66265 * The following will happen: 66266 * 1. App template begins processing. 66267 * 2. First <comp> is matched as a component and its LView is created. 66268 * 3. Second <comp> is matched as a component and its LView is created. 66269 * 4. App template completes processing, so it's time to check child templates. 66270 * 5. First <comp> template is checked. It has a directive, so its def is pushed to blueprint. 66271 * 6. Second <comp> template is checked. Its blueprint has been updated by the first 66272 * <comp> template, but its LView was created before this update, so it is out of sync. 66273 *
66274 * Note that embedded views inside ngFor loops will never be out of sync because these views 66275 * are processed as soon as they are created. 66276 * 66277 * @param tView The `TView` that contains the blueprint for syncing 66278 * @param lView The view to sync 66279 */ 66280 66281 66282function syncViewWithBlueprint(tView, lView) { 66283 for (let i = lView.length; i < tView.blueprint.length; i++) { 66284 lView.push(tView.blueprint[i]); 66285 } 66286} 66287/** 66288 * Adds LView or LContainer to the end of the current view tree. 66289 * 66290 * This structure will be used to traverse through nested views to remove listeners 66291 * and call onDestroy callbacks. 66292 * 66293 * @param lView The view where LView or LContainer should be added 66294 * @param adjustedHostIndex Index of the view's host node in LView[], adjusted for header 66295 * @param lViewOrLContainer The LView or LContainer to add to the view tree 66296 * @returns The state passed in 66297 */ 66298 66299 66300function addToViewTree(lView, lViewOrLContainer) { 66301 // TODO(benlesh/misko): This implementation is incorrect, because it always adds the LContainer 66302 // to the end of the queue, which means if the developer retrieves the LContainers from RNodes out 66303 // of order, the change detection will run out of order, as the act of retrieving the the 66304 // LContainer from the RNode is what adds it to the queue. 66305 if (lView[CHILD_HEAD]) { 66306 lView[CHILD_TAIL][NEXT] = lViewOrLContainer; 66307 } else { 66308 lView[CHILD_HEAD] = lViewOrLContainer; 66309 } 66310 66311 lView[CHILD_TAIL] = lViewOrLContainer; 66312 return lViewOrLContainer; 66313} /////////////////////////////// 66314//// Change detection 66315/////////////////////////////// 66316 66317/** 66318 * Marks current view and all ancestors dirty. 66319 * 66320 * Returns the root view because it is found as a byproduct of marking the view tree 66321 * dirty, and can be used by methods that consume markViewDirty() to easily schedule 66322 * change detection. Otherwise, such methods would need to traverse up the view tree 66323 * an additional time to get the root view and schedule a tick on it. 66324 * 66325 * @param lView The starting LView to mark dirty 66326 * @returns the root LView 66327 */ 66328 66329 66330function markViewDirty(lView) { 66331 while (lView) { 66332 lView[FLAGS] |= 32 66333 /* LViewFlags.Dirty */ 66334 ; 66335 const parent = getLViewParent(lView); // Stop traversing up as soon as you find a root view that wasn't attached to any container 66336 66337 if (isRootView(lView) && !parent) { 66338 return lView; 66339 } // continue otherwise 66340 66341 66342 lView = parent; 66343 } 66344 66345 return null; 66346} 66347 66348function detectChangesInternal(tView, lView, context, notifyErrorHandler = true) { 66349 const rendererFactory = lView[RENDERER_FACTORY]; // Check no changes mode is a dev only mode used to verify that bindings have not changed 66350 // since they were assigned. We do not want to invoke renderer factory functions in that mode 66351 // to avoid any possible side-effects. 66352 66353 const checkNoChangesMode = !!ngDevMode && isInCheckNoChangesMode(); 66354 if (!checkNoChangesMode && rendererFactory.begin) rendererFactory.begin(); 66355 66356 try { 66357 refreshView(tView, lView, tView.template, context); 66358 } catch (error) { 66359 if (notifyErrorHandler) { 66360 handleError(lView, error); 66361 } 66362 66363 throw error; 66364 } finally { 66365 if (!checkNoChangesMode && rendererFactory.end) rendererFactory.end(); 66366 } 66367} 66368 66369function checkNoChangesInternal(tView, lView, context, notifyErrorHandler = true) { 66370 setIsInCheckNoChangesMode(true); 66371 66372 try { 66373 detectChangesInternal(tView, lView, context, notifyErrorHandler); 66374 } finally { 66375 setIsInCheckNoChangesMode(false); 66376 } 66377} 66378 66379function executeViewQueryFn(flags, viewQueryFn, component) { 66380 ngDevMode && assertDefined(viewQueryFn, 'View queries function to execute must be defined.'); 66381 setCurrentQueryIndex(0); 66382 viewQueryFn(flags, component); 66383} /////////////////////////////// 66384//// Bindings & interpolations 66385/////////////////////////////// 66386 66387/** 66388 * Stores meta-data for a property binding to be used by TestBed's `DebugElement.properties`. 66389 * 66390 * In order to support TestBed's `DebugElement.properties` we need to save, for each binding: 66391 * - a bound property name; 66392 * - a static parts of interpolated strings; 66393 * 66394 * A given property metadata is saved at the binding's index in the `TView.data` (in other words, a 66395 * property binding metadata will be stored in `TView.data` at the same index as a bound value in 66396 * `LView`). Metadata are represented as `INTERPOLATION_DELIMITER`-delimited string with the 66397 * following format: 66398 * - `propertyName` for bound properties; 66399 * - `propertyName�prefix�interpolation_static_part1�..interpolation_static_partN�suffix` for 66400 * interpolated properties. 66401 * 66402 * @param tData `TData` where meta-data will be saved; 66403 * @param tNode `TNode` that is a target of the binding; 66404 * @param propertyName bound property name; 66405 * @param bindingIndex binding index in `LView` 66406 * @param interpolationParts static interpolation parts (for property interpolations) 66407 */ 66408 66409 66410function storePropertyBindingMetadata(tData, tNode, propertyName, bindingIndex, ...interpolationParts) { 66411 // Binding meta-data are stored only the first time a given property instruction is processed. 66412 // Since we don't have a concept of the "first update pass" we need to check for presence of the 66413 // binding meta-data to decide if one should be stored (or if was stored already). 66414 if (tData[bindingIndex] === null) {
vendor: 9,123 bytes, lines 66415-66702
66415 if (tNode.inputs == null || !tNode.inputs[propertyName]) { 66416 const propBindingIdxs = tNode.propertyBindings || (tNode.propertyBindings = []); 66417 propBindingIdxs.push(bindingIndex); 66418 let bindingMetadata = propertyName; 66419 66420 if (interpolationParts.length > 0) { 66421 bindingMetadata += INTERPOLATION_DELIMITER + interpolationParts.join(INTERPOLATION_DELIMITER); 66422 } 66423 66424 tData[bindingIndex] = bindingMetadata; 66425 } 66426 } 66427} 66428 66429function getOrCreateLViewCleanup(view) { 66430 // top level variables should not be exported for performance reasons (PERF_NOTES.md) 66431 return view[CLEANUP] || (view[CLEANUP] = ngDevMode ? new LCleanup() : []); 66432} 66433 66434function getOrCreateTViewCleanup(tView) { 66435 return tView.cleanup || (tView.cleanup = ngDevMode ? new TCleanup() : []); 66436} 66437/** 66438 * There are cases where the sub component's renderer needs to be included 66439 * instead of the current renderer (see the componentSyntheticHost* instructions). 66440 */ 66441 66442 66443function loadComponentRenderer(currentDef, tNode, lView) { 66444 // TODO(FW-2043): the `currentDef` is null when host bindings are invoked while creating root 66445 // component (see packages/core/src/render3/component.ts). This is not consistent with the process 66446 // of creating inner components, when current directive index is available in the state. In order 66447 // to avoid relying on current def being `null` (thus special-casing root component creation), the 66448 // process of creating root component should be unified with the process of creating inner 66449 // components. 66450 if (currentDef === null || isComponentDef(currentDef)) { 66451 lView = unwrapLView(lView[tNode.index]); 66452 } 66453 66454 return lView[RENDERER]; 66455} 66456/** Handles an error thrown in an LView. */ 66457 66458 66459function handleError(lView, error) { 66460 const injector = lView[INJECTOR$1]; 66461 const errorHandler = injector ? injector.get(ErrorHandler, null) : null; 66462 errorHandler && errorHandler.handleError(error); 66463} 66464/** 66465 * Set the inputs of directives at the current node to corresponding value. 66466 * 66467 * @param tView The current TView 66468 * @param lView the `LView` which contains the directives. 66469 * @param inputs mapping between the public "input" name and privately-known, 66470 * possibly minified, property names to write to. 66471 * @param value Value to set. 66472 */ 66473 66474 66475function setInputsForProperty(tView, lView, inputs, publicName, value) { 66476 for (let i = 0; i < inputs.length;) { 66477 const index = inputs[i++]; 66478 const privateName = inputs[i++]; 66479 const instance = lView[index]; 66480 ngDevMode && assertIndexInRange(lView, index); 66481 const def = tView.data[index]; 66482 66483 if (def.setInput !== null) { 66484 def.setInput(instance, value, publicName, privateName); 66485 } else { 66486 instance[privateName] = value; 66487 } 66488 } 66489} 66490/** 66491 * Updates a text binding at a given index in a given LView. 66492 */ 66493 66494 66495function textBindingInternal(lView, index, value) { 66496 ngDevMode && assertString(value, 'Value should be a string'); 66497 ngDevMode && assertNotSame(value, NO_CHANGE, 'value should not be NO_CHANGE'); 66498 ngDevMode && assertIndexInRange(lView, index); 66499 const element = getNativeByIndex(index, lView); 66500 ngDevMode && assertDefined(element, 'native element should exist'); 66501 updateTextNode(lView[RENDERER], element, value); 66502} 66503/** 66504 * @license 66505 * Copyright Google LLC All Rights Reserved. 66506 * 66507 * Use of this source code is governed by an MIT-style license that can be 66508 * found in the LICENSE file at https://angular.io/license 66509 */ 66510 66511/** 66512 * Compute the static styling (class/style) from `TAttributes`. 66513 * 66514 * This function should be called during `firstCreatePass` only. 66515 * 66516 * @param tNode The `TNode` into which the styling information should be loaded. 66517 * @param attrs `TAttributes` containing the styling information. 66518 * @param writeToHost Where should the resulting static styles be written? 66519 * - `false` Write to `TNode.stylesWithoutHost` / `TNode.classesWithoutHost` 66520 * - `true` Write to `TNode.styles` / `TNode.classes` 66521 */ 66522 66523 66524function computeStaticStyling(tNode, attrs, writeToHost) { 66525 ngDevMode && assertFirstCreatePass(getTView(), 'Expecting to be called in first template pass only'); 66526 let styles = writeToHost ? tNode.styles : null; 66527 let classes = writeToHost ? tNode.classes : null; 66528 let mode = 0; 66529 66530 if (attrs !== null) { 66531 for (let i = 0; i < attrs.length; i++) { 66532 const value = attrs[i]; 66533 66534 if (typeof value === 'number') { 66535 mode = value; 66536 } else if (mode == 1 66537 /* AttributeMarker.Classes */ 66538 ) { 66539 classes = concatStringsWithSpace(classes, value); 66540 } else if (mode == 2 66541 /* AttributeMarker.Styles */ 66542 ) { 66543 const style = value; 66544 const styleValue = attrs[++i]; 66545 styles = concatStringsWithSpace(styles, style + ': ' + styleValue + ';'); 66546 } 66547 } 66548 } 66549 66550 writeToHost ? tNode.styles = styles : tNode.stylesWithoutHost = styles; 66551 writeToHost ? tNode.classes = classes : tNode.classesWithoutHost = classes; 66552} 66553/** 66554 * @license 66555 * Copyright Google LLC All Rights Reserved. 66556 * 66557 * Use of this source code is governed by an MIT-style license that can be 66558 * found in the LICENSE file at https://angular.io/license 66559 */ 66560 66561 66562function collectNativeNodes(tView, lView, tNode, result, isProjection = false) { 66563 while (tNode !== null) { 66564 ngDevMode && assertTNodeType(tNode, 3 66565 /* TNodeType.AnyRNode */ 66566 | 12 66567 /* TNodeType.AnyContainer */ 66568 | 16 66569 /* TNodeType.Projection */ 66570 | 32 66571 /* TNodeType.Icu */ 66572 ); 66573 const lNode = lView[tNode.index]; 66574 66575 if (lNode !== null) { 66576 result.push(unwrapRNode(lNode)); 66577 } // A given lNode can represent either a native node or a LContainer (when it is a host of a 66578 // ViewContainerRef). When we find a LContainer we need to descend into it to collect root nodes 66579 // from the views in this container. 66580 66581 66582 if (isLContainer(lNode)) { 66583 for (let i = CONTAINER_HEADER_OFFSET; i < lNode.length; i++) { 66584 const lViewInAContainer = lNode[i]; 66585 const lViewFirstChildTNode = lViewInAContainer[TVIEW].firstChild; 66586 66587 if (lViewFirstChildTNode !== null) { 66588 collectNativeNodes(lViewInAContainer[TVIEW], lViewInAContainer, lViewFirstChildTNode, result); 66589 } 66590 } 66591 } 66592 66593 const tNodeType = tNode.type; 66594 66595 if (tNodeType & 8 66596 /* TNodeType.ElementContainer */ 66597 ) { 66598 collectNativeNodes(tView, lView, tNode.child, result); 66599 } else if (tNodeType & 32 66600 /* TNodeType.Icu */ 66601 ) { 66602 const nextRNode = icuContainerIterate(tNode, lView); 66603 let rNode; 66604 66605 while (rNode = nextRNode()) { 66606 result.push(rNode); 66607 } 66608 } else if (tNodeType & 16 66609 /* TNodeType.Projection */ 66610 ) { 66611 const nodesInSlot = getProjectionNodes(lView, tNode); 66612 66613 if (Array.isArray(nodesInSlot)) { 66614 result.push(...nodesInSlot); 66615 } else { 66616 const parentView = getLViewParent(lView[DECLARATION_COMPONENT_VIEW]); 66617 ngDevMode && assertParentView(parentView); 66618 collectNativeNodes(parentView[TVIEW], parentView, nodesInSlot, result, true); 66619 } 66620 } 66621 66622 tNode = isProjection ? tNode.projectionNext : tNode.next; 66623 } 66624 66625 return result; 66626} 66627/** 66628 * @license 66629 * Copyright Google LLC All Rights Reserved. 66630 * 66631 * Use of this source code is governed by an MIT-style license that can be 66632 * found in the LICENSE file at https://angular.io/license 66633 */ 66634 66635 66636class ViewRef$1 { 66637 constructor( 66638 /** 66639 * This represents `LView` associated with the component when ViewRef is a ChangeDetectorRef. 66640 * 66641 * When ViewRef is created for a dynamic component, this also represents the `LView` for the 66642 * component. 66643 * 66644 * For a "regular" ViewRef created for an embedded view, this is the `LView` for the embedded 66645 * view. 66646 * 66647 * @internal 66648 */ 66649 _lView, 66650 /** 66651 * This represents the `LView` associated with the point where `ChangeDetectorRef` was 66652 * requested. 66653 * 66654 * This may be different from `_lView` if the `_cdRefInjectingView` is an embedded view. 66655 */ 66656 _cdRefInjectingView) { 66657 this._lView = _lView; 66658 this._cdRefInjectingView = _cdRefInjectingView; 66659 this._appRef = null; 66660 this._attachedToViewContainer = false; 66661 } 66662 66663 get rootNodes() { 66664 const lView = this._lView; 66665 const tView = lView[TVIEW]; 66666 return collectNativeNodes(tView, lView, tView.firstChild, []); 66667 } 66668 66669 get context() { 66670 return this._lView[CONTEXT]; 66671 } 66672 66673 set context(value) { 66674 this._lView[CONTEXT] = value; 66675 } 66676 66677 get destroyed() { 66678 return (this._lView[FLAGS] & 128 66679 /* LViewFlags.Destroyed */ 66680 ) === 128 66681 /* LViewFlags.Destroyed */ 66682 ; 66683 } 66684 66685 destroy() { 66686 if (this._appRef) { 66687 this._appRef.detachView(this); 66688 } else if (this._attachedToViewContainer) { 66689 const parent = this._lView[PARENT]; 66690 66691 if (isLContainer(parent)) { 66692 const viewRefs = parent[VIEW_REFS]; 66693 const index = viewRefs ? viewRefs.indexOf(this) : -1; 66694 66695 if (index > -1) { 66696 ngDevMode && assertEqual(index, parent.indexOf(this._lView) - CONTAINER_HEADER_OFFSET, 'An attached view should be in the same position within its container as its ViewRef in the VIEW_REFS array.'); 66697 detachView(parent, index); 66698 removeFromArray(viewRefs, index); 66699 } 66700 } 66701 66702 this._attachedToViewContainer = false;
66703 } 66704 66705 destroyLView(this._lView[TVIEW], this._lView); 66706 } 66707 66708 onDestroy(callback) { 66709 storeCleanupWithContext(this._lView[TVIEW], this._lView, null, callback); 66710 } 66711 /** 66712 * Marks a view and all of its ancestors dirty. 66713 * 66714 * This can be used to ensure an {@link ChangeDetectionStrategy#OnPush OnPush} component is 66715 * checked when it needs to be re-rendered but the two normal triggers haven't marked it 66716 * dirty (i.e. inputs haven't changed and events haven't fired in the view). 66717 * 66718 * <!-- TODO: Add a link to a chapter on OnPush components --> 66719 * 66720 * @usageNotes 66721 * ### Example 66722 * 66723 * ```typescript 66724 * @Component({ 66725 * selector: 'app-root', 66726 * template: `Number of ticks: {{numberOfTicks}}` 66727 * changeDetection: ChangeDetectionStrategy.OnPush, 66728 * }) 66729 * class AppComponent { 66730 * numberOfTicks = 0; 66731 * 66732 * constructor(private ref: ChangeDetectorRef) { 66733 * setInterval(() => { 66734 * this.numberOfTicks++; 66735 * // the following is required, otherwise the view will not be updated 66736 * this.ref.markForCheck(); 66737 * }, 1000); 66738 * } 66739 * } 66740 * ``` 66741 */ 66742 66743 66744 markForCheck() { 66745 markViewDirty(this._cdRefInjectingView || this._lView); 66746 } 66747 /** 66748 * Detaches the view from the change detection tree. 66749 * 66750 * Detached views will not be checked during change detection runs until they are 66751 * re-attached, even if they are dirty. `detach` can be used in combination with 66752 * {@link ChangeDetectorRef#detectChanges detectChanges} to implement local change 66753 * detection checks. 66754 * 66755 * <!-- TODO: Add a link to a chapter on detach/reattach/local digest --> 66756 * <!-- TODO: Add a live demo once ref.detectChanges is merged into master --> 66757 * 66758 * @usageNotes 66759 * ### Example 66760 * 66761 * The following example defines a component with a large list of readonly data. 66762 * Imagine the data changes constantly, many times per second. For performance reasons, 66763 * we want to check and update the list every five seconds. We can do that by detaching 66764 * the component's change detector and doing a local check every five seconds. 66765 * 66766 * ```typescript 66767 * class DataProvider { 66768 * // in a real application the returned data will be different every time 66769 * get data() { 66770 * return [1,2,3,4,5]; 66771 * } 66772 * } 66773 * 66774 * @Component({ 66775 * selector: 'giant-list', 66776 * template: ` 66777 * <li *ngFor="let d of dataProvider.data">Data {{d}}</li> 66778 * `, 66779 * }) 66780 * class GiantList { 66781 * constructor(private ref: ChangeDetectorRef, private dataProvider: DataProvider) { 66782 * ref.detach(); 66783 * setInterval(() => { 66784 * this.ref.detectChanges(); 66785 * }, 5000); 66786 * } 66787 * } 66788 * 66789 * @Component({ 66790 * selector: 'app', 66791 * providers: [DataProvider], 66792 * template: ` 66793 * <giant-list><giant-list> 66794 * `, 66795 * }) 66796 * class App { 66797 * } 66798 * ``` 66799 */ 66800 66801 66802 detach() { 66803 this._lView[FLAGS] &= ~64 66804 /* LViewFlags.Attached */ 66805 ; 66806 } 66807 /** 66808 * Re-attaches a view to the change detection tree. 66809 * 66810 * This can be used to re-attach views that were previously detached from the tree 66811 * using {@link ChangeDetectorRef#detach detach}. Views are attached to the tree by default. 66812 * 66813 * <!-- TODO: Add a link to a chapter on detach/reattach/local digest --> 66814 * 66815 * @usageNotes 66816 * ### Example 66817 * 66818 * The following example creates a component displaying `live` data. The component will detach 66819 * its change detector from the main change detector tree when the component's live property 66820 * is set to false. 66821 * 66822 * ```typescript 66823 * class DataProvider { 66824 * data = 1; 66825 * 66826 * constructor() { 66827 * setInterval(() => { 66828 * this.data = this.data * 2; 66829 * }, 500); 66830 * } 66831 * } 66832 * 66833 * @Component({ 66834 * selector: 'live-data', 66835 * inputs: ['live'], 66836 * template: 'Data: {{dataProvider.data}}' 66837 * }) 66838 * class LiveData { 66839 * constructor(private ref: ChangeDetectorRef, private dataProvider: DataProvider) {} 66840 * 66841 * set live(value) { 66842 * if (value) { 66843 * this.ref.reattach(); 66844 * } else { 66845 * this.ref.detach(); 66846 * } 66847 * } 66848 * } 66849 * 66850 * @Component({ 66851 * selector: 'app-root', 66852 * providers: [DataProvider], 66853 * template: ` 66854 * Live Update: <input type="checkbox" [(ngModel)]="live"> 66855 * <live-data [live]="live"><live-data> 66856 * `, 66857 * }) 66858 * class AppComponent { 66859 * live = true; 66860 * } 66861 * ``` 66862 */ 66863 66864 66865 reattach() { 66866 this._lView[FLAGS] |= 64 66867 /* LViewFlags.Attached */ 66868 ; 66869 } 66870 /** 66871 * Checks the view and its children. 66872 * 66873 * This can also be used in combination with {@link ChangeDetectorRef#detach detach} to implement 66874 * local change detection checks. 66875 * 66876 * <!-- TODO: Add a link to a chapter on detach/reattach/local digest --> 66877 * <!-- TODO: Add a live demo once ref.detectChanges is merged into master --> 66878 * 66879 * @usageNotes 66880 * ### Example 66881 * 66882 * The following example defines a component with a large list of readonly data. 66883 * Imagine, the data changes constantly, many times per second. For performance reasons, 66884 * we want to check and update the list every five seconds. 66885 * 66886 * We can do that by detaching the component's change detector and doing a local change detection 66887 * check every five seconds. 66888 * 66889 * See {@link ChangeDetectorRef#detach detach} for more information. 66890 */ 66891 66892 66893 detectChanges() { 66894 detectChangesInternal(this._lView[TVIEW], this._lView, this.context); 66895 } 66896 /** 66897 * Checks the change detector and its children, and throws if any changes are detected. 66898 * 66899 * This is used in development mode to verify that running change detection doesn't 66900 * introduce other changes. 66901 */ 66902 66903 66904 checkNoChanges() { 66905 if (ngDevMode) { 66906 checkNoChangesInternal(this._lView[TVIEW], this._lView, this.context); 66907 } 66908 } 66909 66910 attachToViewContainerRef() { 66911 if (this._appRef) { 66912 throw new RuntimeError(902 66913 /* RuntimeErrorCode.VIEW_ALREADY_ATTACHED */ 66914 , ngDevMode && 'This view is already attached directly to the ApplicationRef!'); 66915 } 66916 66917 this._attachedToViewContainer = true; 66918 } 66919 66920 detachFromAppRef() { 66921 this._appRef = null; 66922 renderDetachView(this._lView[TVIEW], this._lView); 66923 } 66924 66925 attachToAppRef(appRef) { 66926 if (this._attachedToViewContainer) { 66927 throw new RuntimeError(902 66928 /* RuntimeErrorCode.VIEW_ALREADY_ATTACHED */
66929 , ngDevMode && 'This view is already attached to a ViewContainer!'); 66930 } 66931 66932 this._appRef = appRef; 66933 } 66934 66935} 66936/** @internal */ 66937 66938 66939class RootViewRef extends ViewRef$1 { 66940 constructor(_view) { 66941 super(_view); 66942 this._view = _view; 66943 } 66944 66945 detectChanges() { 66946 const lView = this._view; 66947 const tView = lView[TVIEW]; 66948 const context = lView[CONTEXT]; 66949 detectChangesInternal(tView, lView, context, false); 66950 } 66951 66952 checkNoChanges() { 66953 if (ngDevMode) { 66954 const lView = this._view; 66955 const tView = lView[TVIEW]; 66956 const context = lView[CONTEXT]; 66957 checkNoChangesInternal(tView, lView, context, false); 66958 } 66959 } 66960 66961 get context() { 66962 return null; 66963 } 66964 66965} 66966/** 66967 * @license 66968 * Copyright Google LLC All Rights Reserved. 66969 * 66970 * Use of this source code is governed by an MIT-style license that can be 66971 * found in the LICENSE file at https://angular.io/license 66972 */ 66973 66974 66975class ComponentFactoryResolver extends ComponentFactoryResolver$1 { 66976 /** 66977 * @param ngModule The NgModuleRef to which all resolved factories are bound. 66978 */ 66979 constructor(ngModule) { 66980 super(); 66981 this.ngModule = ngModule; 66982 } 66983 66984 resolveComponentFactory(component) { 66985 ngDevMode && assertComponentType(component); 66986 const componentDef = getComponentDef(component); 66987 return new ComponentFactory(componentDef, this.ngModule); 66988 } 66989 66990} 66991 66992function toRefArray(map) { 66993 const array = []; 66994 66995 for (let nonMinified in map) { 66996 if (map.hasOwnProperty(nonMinified)) { 66997 const minified = map[nonMinified]; 66998 array.push({ 66999 propName: minified, 67000 templateName: nonMinified 67001 }); 67002 } 67003 } 67004 67005 return array; 67006} 67007 67008function getNamespace(elementName) { 67009 const name = elementName.toLowerCase(); 67010 return name === 'svg' ? SVG_NAMESPACE : name === 'math' ? MATH_ML_NAMESPACE : null; 67011} 67012/** 67013 * Injector that looks up a value using a specific injector, before falling back to the module 67014 * injector. Used primarily when creating components or embedded views dynamically. 67015 */ 67016 67017 67018class ChainedInjector { 67019 constructor(injector, parentInjector) { 67020 this.injector = injector; 67021 this.parentInjector = parentInjector; 67022 } 67023 67024 get(token, notFoundValue, flags) { 67025 const value = this.injector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, flags); 67026 67027 if (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR || notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) { 67028 // Return the value from the root element injector when 67029 // - it provides it 67030 // (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) 67031 // - the module injector should not be checked 67032 // (notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) 67033 return value; 67034 } 67035 67036 return this.parentInjector.get(token, notFoundValue, flags); 67037 } 67038 67039} 67040/** 67041 * ComponentFactory interface implementation. 67042 */ 67043 67044 67045class ComponentFactory extends ComponentFactory$1 { 67046 /** 67047 * @param componentDef The component definition. 67048 * @param ngModule The NgModuleRef to which the factory is bound. 67049 */ 67050 constructor(componentDef, ngModule) { 67051 super(); 67052 this.componentDef = componentDef; 67053 this.ngModule = ngModule; 67054 this.componentType = componentDef.type; 67055 this.selector = stringifyCSSSelectorList(componentDef.selectors); 67056 this.ngContentSelectors = componentDef.ngContentSelectors ? componentDef.ngContentSelectors : []; 67057 this.isBoundToModule = !!ngModule; 67058 } 67059 67060 get inputs() { 67061 return toRefArray(this.componentDef.inputs); 67062 } 67063 67064 get outputs() { 67065 return toRefArray(this.componentDef.outputs); 67066 } 67067 67068 create(injector, projectableNodes, rootSelectorOrNode, environmentInjector) { 67069 environmentInjector = environmentInjector || this.ngModule; 67070 let realEnvironmentInjector = environmentInjector instanceof EnvironmentInjector ? environmentInjector : environmentInjector?.injector; 67071 67072 if (realEnvironmentInjector && this.componentDef.getStandaloneInjector !== null) { 67073 realEnvironmentInjector = this.componentDef.getStandaloneInjector(realEnvironmentInjector) || realEnvironmentInjector; 67074 } 67075 67076 const rootViewInjector = realEnvironmentInjector ? new ChainedInjector(injector, realEnvironmentInjector) : injector; 67077 const rendererFactory = rootViewInjector.get(RendererFactory2, null); 67078 67079 if (rendererFactory === null) { 67080 throw new RuntimeError(407 67081 /* RuntimeErrorCode.RENDERER_NOT_FOUND */ 67082 , ngDevMode && 'Angular was not able to inject a renderer (RendererFactory2). ' + 'Likely this is due to a broken DI hierarchy. ' + 'Make sure that any injector used to create this component has a correct parent.'); 67083 } 67084 67085 const sanitizer = rootViewInjector.get(Sanitizer, null); 67086 const hostRenderer = rendererFactory.createRenderer(null, this.componentDef); // Determine a tag name used for creating host elements when this component is created 67087 // dynamically. Default to 'div' if this component did not specify any tag name in its selector. 67088 67089 const elementName = this.componentDef.selectors[0][0] || 'div'; 67090 const hostRNode = rootSelectorOrNode ? locateHostElement(hostRenderer, rootSelectorOrNode, this.componentDef.encapsulation) : createElementNode(hostRenderer, elementName, getNamespace(elementName)); 67091 const rootFlags = this.componentDef.onPush ? 32 67092 /* LViewFlags.Dirty */ 67093 | 256 67094 /* LViewFlags.IsRoot */ 67095 : 16 67096 /* LViewFlags.CheckAlways */ 67097 | 256 67098 /* LViewFlags.IsRoot */ 67099 ; // Create the root view. Uses empty TView and ContentTemplate. 67100 67101 const rootTView = createTView(0 67102 /* TViewType.Root */ 67103 , null, null, 1, 0, null, null, null, null, null); 67104 const rootLView = createLView(null, rootTView, null, rootFlags, null, null, rendererFactory, hostRenderer, sanitizer, rootViewInjector, null); // rootView is the parent when bootstrapping 67105 // TODO(misko): it looks like we are entering view here but we don't really need to as 67106 // `renderView` does that. However as the code is written it is needed because 67107 // `createRootComponentView` and `createRootComponent` both read global state. Fixing those 67108 // issues would allow us to drop this. 67109
67110 enterView(rootLView); 67111 let component; 67112 let tElementNode; 67113 67114 try { 67115 const componentView = createRootComponentView(hostRNode, this.componentDef, rootLView, rendererFactory, hostRenderer); 67116 67117 if (hostRNode) { 67118 if (rootSelectorOrNode) { 67119 setUpAttributes(hostRenderer, hostRNode, ['ng-version', VERSION.full]); 67120 } else { 67121 // If host element is created as a part of this function call (i.e. `rootSelectorOrNode` 67122 // is not defined), also apply attributes and classes extracted from component selector. 67123 // Extract attributes and classes from the first selector only to match VE behavior. 67124 const { 67125 attrs, 67126 classes 67127 } = extractAttrsAndClassesFromSelector(this.componentDef.selectors[0]); 67128 67129 if (attrs) { 67130 setUpAttributes(hostRenderer, hostRNode, attrs); 67131 } 67132 67133 if (classes && classes.length > 0) { 67134 writeDirectClass(hostRenderer, hostRNode, classes.join(' ')); 67135 } 67136 } 67137 } 67138 67139 tElementNode = getTNode(rootTView, HEADER_OFFSET); 67140 67141 if (projectableNodes !== undefined) { 67142 const projection = tElementNode.projection = []; 67143 67144 for (let i = 0; i < this.ngContentSelectors.length; i++) { 67145 const nodesforSlot = projectableNodes[i]; // Projectable nodes can be passed as array of arrays or an array of iterables (ngUpgrade 67146 // case). Here we do normalize passed data structure to be an array of arrays to avoid 67147 // complex checks down the line. 67148 // We also normalize the length of the passed in projectable nodes (to match the number of 67149 // <ng-container> slots defined by a component). 67150 67151 projection.push(nodesforSlot != null ? Array.from(nodesforSlot) : null); 67152 } 67153 } // TODO: should LifecycleHooksFeature and other host features be generated by the compiler and 67154 // executed here? 67155 // Angular 5 reference: https://stackblitz.com/edit/lifecycle-hooks-vcref 67156 67157 67158 component = createRootComponent(componentView, this.componentDef, rootLView, [LifecycleHooksFeature]); 67159 renderView(rootTView, rootLView, null); 67160 } finally { 67161 leaveView(); 67162 } 67163 67164 return new ComponentRef(this.componentType, component, createElementRef(tElementNode, rootLView), rootLView, tElementNode); 67165 } 67166 67167} 67168 67169const componentFactoryResolver = new ComponentFactoryResolver(); 67170/** 67171 * Creates a ComponentFactoryResolver and stores it on the injector. Or, if the 67172 * ComponentFactoryResolver 67173 * already exists, retrieves the existing ComponentFactoryResolver. 67174 * 67175 * @returns The ComponentFactoryResolver instance to use 67176 */ 67177 67178function injectComponentFactoryResolver() { 67179 return componentFactoryResolver; 67180} 67181/** 67182 * Represents an instance of a Component created via a {@link ComponentFactory}. 67183 * 67184 * `ComponentRef` provides access to the Component Instance as well other objects related to this 67185 * Component Instance and allows you to destroy the Component Instance via the {@link #destroy} 67186 * method. 67187 * 67188 */ 67189 67190 67191class ComponentRef extends ComponentRef$1 { 67192 constructor(componentType, instance, location, _rootLView, _tNode) { 67193 super(); 67194 this.location = location; 67195 this._rootLView = _rootLView; 67196 this._tNode = _tNode;
67197 this.instance = instance; 67198 this.hostView = this.changeDetectorRef = new RootViewRef(_rootLView); 67199 this.componentType = componentType; 67200 } 67201 67202 setInput(name, value) { 67203 const inputData = this._tNode.inputs; 67204 let dataValue; 67205 67206 if (inputData !== null && (dataValue = inputData[name])) { 67207 const lView = this._rootLView; 67208 setInputsForProperty(lView[TVIEW], lView, dataValue, name, value); 67209 markDirtyIfOnPush(lView, this._tNode.index); 67210 } else { 67211 if (ngDevMode) { 67212 const cmpNameForError = stringifyForError(this.componentType); 67213 let message = `Can't set value of the '${name}' input on the '${cmpNameForError}' component. `; 67214 message += `Make sure that the '${name}' property is annotated with @Input() or a mapped @Input('${name}') exists.`; 67215 reportUnknownPropertyError(message); 67216 } 67217 } 67218 } 67219 67220 get injector() { 67221 return new NodeInjector(this._tNode, this._rootLView); 67222 } 67223 67224 destroy() { 67225 this.hostView.destroy(); 67226 } 67227 67228 onDestroy(callback) { 67229 this.hostView.onDestroy(callback); 67230 } 67231 67232} // TODO: A hack to not pull in the NullInjector from @angular/core. 67233 67234 67235const NULL_INJECTOR = { 67236 get: (token, notFoundValue) => { 67237 throwProviderNotFoundError(token, 'NullInjector'); 67238 } 67239}; 67240/** 67241 * Creates the root component view and the root component node. 67242 * 67243 * @param rNode Render host element. 67244 * @param def ComponentDef 67245 * @param rootView The parent view where the host node is stored 67246 * @param rendererFactory Factory to be used for creating child renderers. 67247 * @param hostRenderer The current renderer 67248 * @param sanitizer The sanitizer, if provided 67249 * 67250 * @returns Component view created 67251 */ 67252 67253function createRootComponentView(rNode, def, rootView, rendererFactory, hostRenderer, sanitizer) { 67254 const tView = rootView[TVIEW]; 67255 const index = HEADER_OFFSET; 67256 ngDevMode && assertIndexInRange(rootView, index); 67257 rootView[index] = rNode; // '#host' is added here as we don't know the real host DOM name (we don't want to read it) and at 67258 // the same time we want to communicate the debug `TNode` that this is a special `TNode` 67259 // representing a host element. 67260 67261 const tNode = getOrCreateTNode(tView, index, 2 67262 /* TNodeType.Element */ 67263 , '#host', null); 67264 const mergedAttrs = tNode.mergedAttrs = def.hostAttrs; 67265 67266 if (mergedAttrs !== null) { 67267 computeStaticStyling(tNode, mergedAttrs, true); 67268 67269 if (rNode !== null) { 67270 setUpAttributes(hostRenderer, rNode, mergedAttrs); 67271 67272 if (tNode.classes !== null) { 67273 writeDirectClass(hostRenderer, rNode, tNode.classes); 67274 } 67275 67276 if (tNode.styles !== null) { 67277 writeDirectStyle(hostRenderer, rNode, tNode.styles); 67278 } 67279 } 67280 } 67281 67282 const viewRenderer = rendererFactory.createRenderer(rNode, def); 67283 const componentView = createLView(rootView, getOrCreateComponentTView(def), null, def.onPush ? 32 67284 /* LViewFlags.Dirty */ 67285 : 16 67286 /* LViewFlags.CheckAlways */ 67287 , rootView[index], tNode, rendererFactory, viewRenderer, sanitizer || null, null, null); 67288 67289 if (tView.firstCreatePass) { 67290 diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, rootView), tView, def.type); 67291 markAsComponentHost(tView, tNode); 67292 initTNodeFlags(tNode, rootView.length, 1); 67293 } 67294 67295 addToViewTree(rootView, componentView); // Store component view at node index, with node as the HOST 67296 67297 return rootView[index] = componentView; 67298} 67299/** 67300 * Creates a root component and sets it up with features and host bindings.Shared by 67301 * renderComponent() and ViewContainerRef.createComponent(). 67302 */ 67303 67304 67305function createRootComponent(componentView, componentDef, rootLView, hostFeatures) { 67306 const tView = rootLView[TVIEW]; // Create directive instance with factory() and store at next index in viewData 67307 67308 const component = instantiateRootComponent(tView, rootLView, componentDef); // Root view only contains an instance of this component, 67309 // so we use a reference to that component instance as a context. 67310 67311 componentView[CONTEXT] = rootLView[CONTEXT] = component; 67312 67313 if (hostFeatures !== null) { 67314 for (const feature of hostFeatures) { 67315 feature(component, componentDef); 67316 } 67317 } // We want to generate an empty QueryList for root content queries for backwards 67318 // compatibility with ViewEngine. 67319 67320 67321 if (componentDef.contentQueries) { 67322 const tNode = getCurrentTNode(); 67323 ngDevMode && assertDefined(tNode, 'TNode expected'); 67324 componentDef.contentQueries(1
vendor: 23,684 bytes, lines 67325-67999
67325 /* RenderFlags.Create */ 67326 , component, tNode.directiveStart); 67327 } 67328 67329 const rootTNode = getCurrentTNode(); 67330 ngDevMode && assertDefined(rootTNode, 'tNode should have been already created'); 67331 67332 if (tView.firstCreatePass && (componentDef.hostBindings !== null || componentDef.hostAttrs !== null)) { 67333 setSelectedIndex(rootTNode.index); 67334 const rootTView = rootLView[TVIEW]; 67335 registerHostBindingOpCodes(rootTView, rootTNode, rootLView, rootTNode.directiveStart, rootTNode.directiveEnd, componentDef); 67336 invokeHostBindingsInCreationMode(componentDef, component); 67337 } 67338 67339 return component; 67340} 67341/** 67342 * Used to enable lifecycle hooks on the root component. 67343 * 67344 * Include this feature when calling `renderComponent` if the root component 67345 * you are rendering has lifecycle hooks defined. Otherwise, the hooks won't 67346 * be called properly. 67347 * 67348 * Example: 67349 * 67350 * ``` 67351 * renderComponent(AppComponent, {hostFeatures: [LifecycleHooksFeature]}); 67352 * ``` 67353 */ 67354 67355 67356function LifecycleHooksFeature() { 67357 const tNode = getCurrentTNode(); 67358 ngDevMode && assertDefined(tNode, 'TNode is required'); 67359 registerPostOrderHooks(getLView()[TVIEW], tNode); 67360} 67361/** 67362 * @license 67363 * Copyright Google LLC All Rights Reserved. 67364 * 67365 * Use of this source code is governed by an MIT-style license that can be 67366 * found in the LICENSE file at https://angular.io/license 67367 */ 67368 67369 67370function getSuperType(type) { 67371 return Object.getPrototypeOf(type.prototype).constructor; 67372} 67373/** 67374 * Merges the definition from a super class to a sub class. 67375 * @param definition The definition that is a SubClass of another directive of component 67376 * 67377 * @codeGenApi 67378 */ 67379 67380 67381function ɵɵInheritDefinitionFeature(definition) { 67382 let superType = getSuperType(definition.type); 67383 let shouldInheritFields = true; 67384 const inheritanceChain = [definition]; 67385 67386 while (superType) { 67387 let superDef = undefined; 67388 67389 if (isComponentDef(definition)) { 67390 // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance. 67391 superDef = superType.ɵcmp || superType.ɵdir; 67392 } else { 67393 if (superType.ɵcmp) { 67394 throw new RuntimeError(903 67395 /* RuntimeErrorCode.INVALID_INHERITANCE */ 67396 , ngDevMode && `Directives cannot inherit Components. Directive ${stringifyForError(definition.type)} is attempting to extend component ${stringifyForError(superType)}`); 67397 } // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance. 67398 67399 67400 superDef = superType.ɵdir; 67401 } 67402 67403 if (superDef) { 67404 if (shouldInheritFields) { 67405 inheritanceChain.push(superDef); // Some fields in the definition may be empty, if there were no values to put in them that 67406 // would've justified object creation. Unwrap them if necessary. 67407 67408 const writeableDef = definition; 67409 writeableDef.inputs = maybeUnwrapEmpty(definition.inputs); 67410 writeableDef.declaredInputs = maybeUnwrapEmpty(definition.declaredInputs); 67411 writeableDef.outputs = maybeUnwrapEmpty(definition.outputs); // Merge hostBindings 67412 67413 const superHostBindings = superDef.hostBindings; 67414 superHostBindings && inheritHostBindings(definition, superHostBindings); // Merge queries 67415 67416 const superViewQuery = superDef.viewQuery; 67417 const superContentQueries = superDef.contentQueries; 67418 superViewQuery && inheritViewQuery(definition, superViewQuery); 67419 superContentQueries && inheritContentQueries(definition, superContentQueries); // Merge inputs and outputs 67420 67421 fillProperties(definition.inputs, superDef.inputs); 67422 fillProperties(definition.declaredInputs, superDef.declaredInputs); 67423 fillProperties(definition.outputs, superDef.outputs); // Merge animations metadata. 67424 // If `superDef` is a Component, the `data` field is present (defaults to an empty object). 67425 67426 if (isComponentDef(superDef) && superDef.data.animation) { 67427 // If super def is a Component, the `definition` is also a Component, since Directives can 67428 // not inherit Components (we throw an error above and cannot reach this code). 67429 const defData = definition.data; 67430 defData.animation = (defData.animation || []).concat(superDef.data.animation); 67431 } 67432 } // Run parent features 67433 67434 67435 const features = superDef.features; 67436 67437 if (features) { 67438 for (let i = 0; i < features.length; i++) { 67439 const feature = features[i]; 67440 67441 if (feature && feature.ngInherit) { 67442 feature(definition); 67443 } // If `InheritDefinitionFeature` is a part of the current `superDef`, it means that this 67444 // def already has all the necessary information inherited from its super class(es), so we 67445 // can stop merging fields from super classes. However we need to iterate through the 67446 // prototype chain to look for classes that might contain other "features" (like 67447 // NgOnChanges), which we should invoke for the original `definition`. We set the 67448 // `shouldInheritFields` flag to indicate that, essentially skipping fields inheritance 67449 // logic and only invoking functions from the "features" list. 67450 67451 67452 if (feature === ɵɵInheritDefinitionFeature) { 67453 shouldInheritFields = false; 67454 } 67455 } 67456 } 67457 } 67458 67459 superType = Object.getPrototypeOf(superType); 67460 } 67461 67462 mergeHostAttrsAcrossInheritance(inheritanceChain); 67463} 67464/** 67465 * Merge the `hostAttrs` and `hostVars` from the inherited parent to the base class. 67466 * 67467 * @param inheritanceChain A list of `WritableDefs` starting at the top most type and listing 67468 * sub-types in order. For each type take the `hostAttrs` and `hostVars` and merge it with the child 67469 * type. 67470 */ 67471 67472 67473function mergeHostAttrsAcrossInheritance(inheritanceChain) { 67474 let hostVars = 0; 67475 let hostAttrs = null; // We process the inheritance order from the base to the leaves here. 67476 67477 for (let i = inheritanceChain.length - 1; i >= 0; i--) { 67478 const def = inheritanceChain[i]; // For each `hostVars`, we need to add the superclass amount. 67479 67480 def.hostVars = hostVars += def.hostVars; // for each `hostAttrs` we need to merge it with superclass. 67481 67482 def.hostAttrs = mergeHostAttrs(def.hostAttrs, hostAttrs = mergeHostAttrs(hostAttrs, def.hostAttrs)); 67483 } 67484} 67485 67486function maybeUnwrapEmpty(value) { 67487 if (value === EMPTY_OBJ) { 67488 return {}; 67489 } else if (value === EMPTY_ARRAY) { 67490 return []; 67491 } else { 67492 return value; 67493 } 67494} 67495 67496function inheritViewQuery(definition, superViewQuery) { 67497 const prevViewQuery = definition.viewQuery; 67498 67499 if (prevViewQuery) { 67500 definition.viewQuery = (rf, ctx) => { 67501 superViewQuery(rf, ctx); 67502 prevViewQuery(rf, ctx); 67503 }; 67504 } else { 67505 definition.viewQuery = superViewQuery; 67506 } 67507} 67508 67509function inheritContentQueries(definition, superContentQueries) { 67510 const prevContentQueries = definition.contentQueries; 67511 67512 if (prevContentQueries) { 67513 definition.contentQueries = (rf, ctx, directiveIndex) => { 67514 superContentQueries(rf, ctx, directiveIndex); 67515 prevContentQueries(rf, ctx, directiveIndex); 67516 }; 67517 } else { 67518 definition.contentQueries = superContentQueries; 67519 } 67520} 67521 67522function inheritHostBindings(definition, superHostBindings) { 67523 const prevHostBindings = definition.hostBindings; 67524 67525 if (prevHostBindings) { 67526 definition.hostBindings = (rf, ctx) => { 67527 superHostBindings(rf, ctx); 67528 prevHostBindings(rf, ctx); 67529 }; 67530 } else { 67531 definition.hostBindings = superHostBindings; 67532 } 67533} 67534/** 67535 * @license 67536 * Copyright Google LLC All Rights Reserved. 67537 * 67538 * Use of this source code is governed by an MIT-style license that can be 67539 * found in the LICENSE file at https://angular.io/license 67540 */ 67541 67542/** 67543 * Fields which exist on either directive or component definitions, and need to be copied from 67544 * parent to child classes by the `ɵɵCopyDefinitionFeature`. 67545 */ 67546 67547 67548const COPY_DIRECTIVE_FIELDS = [// The child class should use the providers of its parent. 67549'providersResolver' // Not listed here are any fields which are handled by the `ɵɵInheritDefinitionFeature`, such 67550// as inputs, outputs, and host binding functions. 67551]; 67552/** 67553 * Fields which exist only on component definitions, and need to be copied from parent to child 67554 * classes by the `ɵɵCopyDefinitionFeature`. 67555 * 67556 * The type here allows any field of `ComponentDef` which is not also a property of `DirectiveDef`, 67557 * since those should go in `COPY_DIRECTIVE_FIELDS` above. 67558 */ 67559 67560const COPY_COMPONENT_FIELDS = [// The child class should use the template function of its parent, including all template 67561// semantics. 67562'template', 'decls', 'consts', 'vars', 'onPush', 'ngContentSelectors', // The child class should use the CSS styles of its parent, including all styling semantics. 67563'styles', 'encapsulation', // The child class should be checked by the runtime in the same way as its parent. 67564'schemas']; 67565/** 67566 * Copies the fields not handled by the `ɵɵInheritDefinitionFeature` from the supertype of a 67567 * definition. 67568 * 67569 * This exists primarily to support ngcc migration of an existing View Engine pattern, where an 67570 * entire decorator is inherited from a parent to a child class. When ngcc detects this case, it 67571 * generates a skeleton definition on the child class, and applies this feature. 67572 * 67573 * The `ɵɵCopyDefinitionFeature` then copies any needed fields from the parent class' definition, 67574 * including things like the component template function. 67575 * 67576 * @param definition The definition of a child class which inherits from a parent class with its 67577 * own definition. 67578 * 67579 * @codeGenApi 67580 */ 67581 67582function ɵɵCopyDefinitionFeature(definition) { 67583 let superType = getSuperType(definition.type); 67584 let superDef = undefined; 67585 67586 if (isComponentDef(definition)) { 67587 // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance. 67588 superDef = superType.ɵcmp; 67589 } else { 67590 // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance. 67591 superDef = superType.ɵdir; 67592 } // Needed because `definition` fields are readonly. 67593 67594 67595 const defAny = definition; // Copy over any fields that apply to either directives or components. 67596 67597 for (const field of COPY_DIRECTIVE_FIELDS) { 67598 defAny[field] = superDef[field]; 67599 } 67600 67601 if (isComponentDef(superDef)) { 67602 // Copy over any component-specific fields. 67603 for (const field of COPY_COMPONENT_FIELDS) { 67604 defAny[field] = superDef[field]; 67605 } 67606 } 67607} 67608/** 67609 * @license 67610 * Copyright Google LLC All Rights Reserved. 67611 * 67612 * Use of this source code is governed by an MIT-style license that can be 67613 * found in the LICENSE file at https://angular.io/license 67614 */ 67615 67616 67617let _symbolIterator = null; 67618 67619function getSymbolIterator() { 67620 if (!_symbolIterator) { 67621 const Symbol = _global['Symbol']; 67622 67623 if (Symbol && Symbol.iterator) { 67624 _symbolIterator = Symbol.iterator; 67625 } else { 67626 // es6-shim specific logic 67627 const keys = Object.getOwnPropertyNames(Map.prototype); 67628 67629 for (let i = 0; i < keys.length; ++i) { 67630 const key = keys[i]; 67631 67632 if (key !== 'entries' && key !== 'size' && Map.prototype[key] === Map.prototype['entries']) { 67633 _symbolIterator = key; 67634 } 67635 } 67636 } 67637 } 67638 67639 return _symbolIterator; 67640} 67641/** 67642 * @license 67643 * Copyright Google LLC All Rights Reserved. 67644 * 67645 * Use of this source code is governed by an MIT-style license that can be 67646 * found in the LICENSE file at https://angular.io/license 67647 */ 67648 67649 67650function isIterable(obj) { 67651 return obj !== null && typeof obj === 'object' && obj[getSymbolIterator()] !== undefined; 67652} 67653 67654function isListLikeIterable(obj) { 67655 if (!isJsObject(obj)) return false; 67656 return Array.isArray(obj) || !(obj instanceof Map) && // JS Map are iterables but return entries as [k, v] 67657 getSymbolIterator() in obj; // JS Iterable have a Symbol.iterator prop 67658} 67659 67660function areIterablesEqual(a, b, comparator) { 67661 const iterator1 = a[getSymbolIterator()](); 67662 const iterator2 = b[getSymbolIterator()](); 67663 67664 while (true) { 67665 const item1 = iterator1.next(); 67666 const item2 = iterator2.next(); 67667 if (item1.done && item2.done) return true; 67668 if (item1.done || item2.done) return false; 67669 if (!comparator(item1.value, item2.value)) return false; 67670 } 67671} 67672 67673function iterateListLike(obj, fn) { 67674 if (Array.isArray(obj)) { 67675 for (let i = 0; i < obj.length; i++) { 67676 fn(obj[i]); 67677 } 67678 } else { 67679 const iterator = obj[getSymbolIterator()](); 67680 let item; 67681 67682 while (!(item = iterator.next()).done) { 67683 fn(item.value); 67684 } 67685 } 67686} 67687 67688function isJsObject(o) { 67689 return o !== null && (typeof o === 'function' || typeof o === 'object'); 67690} 67691/** 67692 * @license 67693 * Copyright Google LLC All Rights Reserved. 67694 * 67695 * Use of this source code is governed by an MIT-style license that can be 67696 * found in the LICENSE file at https://angular.io/license 67697 */ 67698 67699 67700function devModeEqual(a, b) { 67701 const isListLikeIterableA = isListLikeIterable(a); 67702 const isListLikeIterableB = isListLikeIterable(b); 67703 67704 if (isListLikeIterableA && isListLikeIterableB) { 67705 return areIterablesEqual(a, b, devModeEqual); 67706 } else { 67707 const isAObject = a && (typeof a === 'object' || typeof a === 'function'); 67708 const isBObject = b && (typeof b === 'object' || typeof b === 'function'); 67709 67710 if (!isListLikeIterableA && isAObject && !isListLikeIterableB && isBObject) { 67711 return true; 67712 } else { 67713 return Object.is(a, b); 67714 } 67715 } 67716} 67717/** 67718 * @license 67719 * Copyright Google LLC All Rights Reserved. 67720 * 67721 * Use of this source code is governed by an MIT-style license that can be 67722 * found in the LICENSE file at https://angular.io/license 67723 */ 67724// TODO(misko): consider inlining 67725 67726/** Updates binding and returns the value. */ 67727 67728 67729function updateBinding(lView, bindingIndex, value) { 67730 return lView[bindingIndex] = value; 67731} 67732/** Gets the current binding value. */ 67733 67734 67735function getBinding(lView, bindingIndex) { 67736 ngDevMode && assertIndexInRange(lView, bindingIndex); 67737 ngDevMode && assertNotSame(lView[bindingIndex], NO_CHANGE, 'Stored value should never be NO_CHANGE.'); 67738 return lView[bindingIndex]; 67739} 67740/** 67741 * Updates binding if changed, then returns whether it was updated. 67742 * 67743 * This function also checks the `CheckNoChangesMode` and throws if changes are made. 67744 * Some changes (Objects/iterables) during `CheckNoChangesMode` are exempt to comply with VE 67745 * behavior. 67746 * 67747 * @param lView current `LView` 67748 * @param bindingIndex The binding in the `LView` to check 67749 * @param value New value to check against `lView[bindingIndex]` 67750 * @returns `true` if the bindings has changed. (Throws if binding has changed during 67751 * `CheckNoChangesMode`) 67752 */ 67753 67754 67755function bindingUpdated(lView, bindingIndex, value) { 67756 ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.'); 67757 ngDevMode && assertLessThan(bindingIndex, lView.length, `Slot should have been initialized to NO_CHANGE`); 67758 const oldValue = lView[bindingIndex]; 67759 67760 if (Object.is(oldValue, value)) { 67761 return false; 67762 } else { 67763 if (ngDevMode && isInCheckNoChangesMode()) { 67764 // View engine didn't report undefined values as changed on the first checkNoChanges pass 67765 // (before the change detection was run). 67766 const oldValueToCompare = oldValue !== NO_CHANGE ? oldValue : undefined; 67767 67768 if (!devModeEqual(oldValueToCompare, value)) { 67769 const details = getExpressionChangedErrorDetails(lView, bindingIndex, oldValueToCompare, value); 67770 throwErrorIfNoChangesMode(oldValue === NO_CHANGE, details.oldValue, details.newValue, details.propName); 67771 } // There was a change, but the `devModeEqual` decided that the change is exempt from an error. 67772 // For this reason we exit as if no change. The early exit is needed to prevent the changed 67773 // value to be written into `LView` (If we would write the new value that we would not see it 67774 // as change on next CD.) 67775 67776 67777 return false; 67778 } 67779 67780 lView[bindingIndex] = value; 67781 return true; 67782 } 67783} 67784/** Updates 2 bindings if changed, then returns whether either was updated. */ 67785 67786 67787function bindingUpdated2(lView, bindingIndex, exp1, exp2) { 67788 const different = bindingUpdated(lView, bindingIndex, exp1); 67789 return bindingUpdated(lView, bindingIndex + 1, exp2) || different; 67790} 67791/** Updates 3 bindings if changed, then returns whether any was updated. */ 67792 67793 67794function bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) { 67795 const different = bindingUpdated2(lView, bindingIndex, exp1, exp2); 67796 return bindingUpdated(lView, bindingIndex + 2, exp3) || different; 67797} 67798/** Updates 4 bindings if changed, then returns whether any was updated. */ 67799 67800 67801function bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) { 67802 const different = bindingUpdated2(lView, bindingIndex, exp1, exp2); 67803 return bindingUpdated2(lView, bindingIndex + 2, exp3, exp4) || different; 67804} 67805/** 67806 * @license 67807 * Copyright Google LLC All Rights Reserved. 67808 * 67809 * Use of this source code is governed by an MIT-style license that can be 67810 * found in the LICENSE file at https://angular.io/license 67811 */ 67812 67813/** 67814 * Updates the value of or removes a bound attribute on an Element. 67815 * 67816 * Used in the case of `[attr.title]="value"` 67817 * 67818 * @param name name The name of the attribute. 67819 * @param value value The attribute is removed when value is `null` or `undefined`. 67820 * Otherwise the attribute value is set to the stringified value. 67821 * @param sanitizer An optional function used to sanitize the value. 67822 * @param namespace Optional namespace to use when setting the attribute. 67823 * 67824 * @codeGenApi 67825 */ 67826 67827 67828function ɵɵattribute(name, value, sanitizer, namespace) { 67829 const lView = getLView(); 67830 const bindingIndex = nextBindingIndex(); 67831 67832 if (bindingUpdated(lView, bindingIndex, value)) { 67833 const tView = getTView(); 67834 const tNode = getSelectedTNode(); 67835 elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace); 67836 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, 'attr.' + name, bindingIndex); 67837 } 67838 67839 return ɵɵattribute; 67840} 67841/** 67842 * @license 67843 * Copyright Google LLC All Rights Reserved. 67844 * 67845 * Use of this source code is governed by an MIT-style license that can be 67846 * found in the LICENSE file at https://angular.io/license 67847 */ 67848 67849/** 67850 * Create interpolation bindings with a variable number of expressions. 67851 * 67852 * If there are 1 to 8 expressions `interpolation1()` to `interpolation8()` should be used instead. 67853 * Those are faster because there is no need to create an array of expressions and iterate over it. 67854 * 67855 * `values`: 67856 * - has static text at even indexes, 67857 * - has evaluated expressions at odd indexes. 67858 * 67859 * Returns the concatenated string when any of the arguments changes, `NO_CHANGE` otherwise. 67860 */ 67861 67862 67863function interpolationV(lView, values) { 67864 ngDevMode && assertLessThan(2, values.length, 'should have at least 3 values'); 67865 ngDevMode && assertEqual(values.length % 2, 1, 'should have an odd number of values'); 67866 let isBindingUpdated = false; 67867 let bindingIndex = getBindingIndex(); 67868 67869 for (let i = 1; i < values.length; i += 2) { 67870 // Check if bindings (odd indexes) have changed 67871 isBindingUpdated = bindingUpdated(lView, bindingIndex++, values[i]) || isBindingUpdated; 67872 } 67873 67874 setBindingIndex(bindingIndex); 67875 67876 if (!isBindingUpdated) { 67877 return NO_CHANGE; 67878 } // Build the updated content 67879 67880 67881 let content = values[0]; 67882 67883 for (let i = 1; i < values.length; i += 2) { 67884 content += renderStringify(values[i]) + values[i + 1]; 67885 } 67886 67887 return content; 67888} 67889/** 67890 * Creates an interpolation binding with 1 expression. 67891 * 67892 * @param prefix static value used for concatenation only. 67893 * @param v0 value checked for change. 67894 * @param suffix static value used for concatenation only. 67895 */ 67896 67897 67898function interpolation1(lView, prefix, v0, suffix) { 67899 const different = bindingUpdated(lView, nextBindingIndex(), v0); 67900 return different ? prefix + renderStringify(v0) + suffix : NO_CHANGE; 67901} 67902/** 67903 * Creates an interpolation binding with 2 expressions. 67904 */ 67905 67906 67907function interpolation2(lView, prefix, v0, i0, v1, suffix) { 67908 const bindingIndex = getBindingIndex(); 67909 const different = bindingUpdated2(lView, bindingIndex, v0, v1); 67910 incrementBindingIndex(2); 67911 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + suffix : NO_CHANGE; 67912} 67913/** 67914 * Creates an interpolation binding with 3 expressions. 67915 */ 67916 67917 67918function interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix) { 67919 const bindingIndex = getBindingIndex(); 67920 const different = bindingUpdated3(lView, bindingIndex, v0, v1, v2); 67921 incrementBindingIndex(3); 67922 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + suffix : NO_CHANGE; 67923} 67924/** 67925 * Create an interpolation binding with 4 expressions. 67926 */ 67927 67928 67929function interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix) { 67930 const bindingIndex = getBindingIndex(); 67931 const different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); 67932 incrementBindingIndex(4); 67933 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + renderStringify(v3) + suffix : NO_CHANGE; 67934} 67935/** 67936 * Creates an interpolation binding with 5 expressions. 67937 */ 67938 67939 67940function interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) { 67941 const bindingIndex = getBindingIndex(); 67942 let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); 67943 different = bindingUpdated(lView, bindingIndex + 4, v4) || different; 67944 incrementBindingIndex(5); 67945 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + suffix : NO_CHANGE; 67946} 67947/** 67948 * Creates an interpolation binding with 6 expressions. 67949 */ 67950 67951 67952function interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) { 67953 const bindingIndex = getBindingIndex(); 67954 let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); 67955 different = bindingUpdated2(lView, bindingIndex + 4, v4, v5) || different; 67956 incrementBindingIndex(6); 67957 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + suffix : NO_CHANGE; 67958} 67959/** 67960 * Creates an interpolation binding with 7 expressions. 67961 */ 67962 67963 67964function interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) { 67965 const bindingIndex = getBindingIndex(); 67966 let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); 67967 different = bindingUpdated3(lView, bindingIndex + 4, v4, v5, v6) || different; 67968 incrementBindingIndex(7); 67969 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + i5 + renderStringify(v6) + suffix : NO_CHANGE; 67970} 67971/** 67972 * Creates an interpolation binding with 8 expressions. 67973 */ 67974 67975 67976function interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) { 67977 const bindingIndex = getBindingIndex(); 67978 let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3); 67979 different = bindingUpdated4(lView, bindingIndex + 4, v4, v5, v6, v7) || different; 67980 incrementBindingIndex(8); 67981 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + i5 + renderStringify(v6) + i6 + renderStringify(v7) + suffix : NO_CHANGE; 67982} 67983/** 67984 * 67985 * Update an interpolated attribute on an element with single bound value surrounded by text. 67986 * 67987 * Used when the value passed to a property has 1 interpolated value in it: 67988 * 67989 * ```html 67990 * <div attr.title="prefix{{v0}}suffix"></div> 67991 * ``` 67992 * 67993 * Its compiled representation is:: 67994 * 67995 * ```ts 67996 * ɵɵattributeInterpolate1('title', 'prefix', v0, 'suffix'); 67997 * ``` 67998 * 67999 * @param attrName The name of the attribute to update
68000 * @param prefix Static value used for concatenation only. 68001 * @param v0 Value checked for change. 68002 * @param suffix Static value used for concatenation only. 68003 * @param sanitizer An optional sanitizer function 68004 * @returns itself, so that it may be chained. 68005 * @codeGenApi 68006 */ 68007 68008 68009function ɵɵattributeInterpolate1(attrName, prefix, v0, suffix, sanitizer, namespace) { 68010 const lView = getLView(); 68011 const interpolatedValue = interpolation1(lView, prefix, v0, suffix); 68012 68013 if (interpolatedValue !== NO_CHANGE) { 68014 const tNode = getSelectedTNode(); 68015 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace); 68016 ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 1, prefix, suffix); 68017 } 68018 68019 return ɵɵattributeInterpolate1; 68020} 68021/** 68022 * 68023 * Update an interpolated attribute on an element with 2 bound values surrounded by text. 68024 * 68025 * Used when the value passed to a property has 2 interpolated values in it: 68026 * 68027 * ```html 68028 * <div attr.title="prefix{{v0}}-{{v1}}suffix"></div> 68029 * ``` 68030 * 68031 * Its compiled representation is:: 68032 * 68033 * ```ts 68034 * ɵɵattributeInterpolate2('title', 'prefix', v0, '-', v1, 'suffix'); 68035 * ``` 68036 * 68037 * @param attrName The name of the attribute to update 68038 * @param prefix Static value used for concatenation only. 68039 * @param v0 Value checked for change. 68040 * @param i0 Static value used for concatenation only. 68041 * @param v1 Value checked for change. 68042 * @param suffix Static value used for concatenation only. 68043 * @param sanitizer An optional sanitizer function 68044 * @returns itself, so that it may be chained. 68045 * @codeGenApi 68046 */ 68047 68048 68049function ɵɵattributeInterpolate2(attrName, prefix, v0, i0, v1, suffix, sanitizer, namespace) { 68050 const lView = getLView(); 68051 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix); 68052 68053 if (interpolatedValue !== NO_CHANGE) { 68054 const tNode = getSelectedTNode(); 68055 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace); 68056 ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 2, prefix, i0, suffix); 68057 } 68058 68059 return ɵɵattributeInterpolate2; 68060} 68061/** 68062 * 68063 * Update an interpolated attribute on an element with 3 bound values surrounded by text. 68064 * 68065 * Used when the value passed to a property has 3 interpolated values in it: 68066 * 68067 * ```html 68068 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div> 68069 * ``` 68070 * 68071 * Its compiled representation is:: 68072 * 68073 * ```ts 68074 * ɵɵattributeInterpolate3( 68075 * 'title', 'prefix', v0, '-', v1, '-', v2, 'suffix'); 68076 * ``` 68077 * 68078 * @param attrName The name of the attribute to update 68079 * @param prefix Static value used for concatenation only. 68080 * @param v0 Value checked for change. 68081 * @param i0 Static value used for concatenation only. 68082 * @param v1 Value checked for change. 68083 * @param i1 Static value used for concatenation only. 68084 * @param v2 Value checked for change. 68085 * @param suffix Static value used for concatenation only. 68086 * @param sanitizer An optional sanitizer function 68087 * @returns itself, so that it may be chained. 68088 * @codeGenApi 68089 */ 68090 68091 68092function ɵɵattributeInterpolate3(attrName, prefix, v0, i0, v1, i1, v2, suffix, sanitizer, namespace) { 68093 const lView = getLView(); 68094 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix); 68095 68096 if (interpolatedValue !== NO_CHANGE) { 68097 const tNode = getSelectedTNode(); 68098 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace); 68099 ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 3, prefix, i0, i1, suffix); 68100 } 68101 68102 return ɵɵattributeInterpolate3; 68103} 68104/** 68105 * 68106 * Update an interpolated attribute on an element with 4 bound values surrounded by text. 68107 * 68108 * Used when the value passed to a property has 4 interpolated values in it: 68109 * 68110 * ```html 68111 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div> 68112 * ``` 68113 * 68114 * Its compiled representation is:: 68115 * 68116 * ```ts 68117 * ɵɵattributeInterpolate4( 68118 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix'); 68119 * ``` 68120 * 68121 * @param attrName The name of the attribute to update
68122 * @param prefix Static value used for concatenation only. 68123 * @param v0 Value checked for change. 68124 * @param i0 Static value used for concatenation only. 68125 * @param v1 Value checked for change. 68126 * @param i1 Static value used for concatenation only. 68127 * @param v2 Value checked for change. 68128 * @param i2 Static value used for concatenation only. 68129 * @param v3 Value checked for change. 68130 * @param suffix Static value used for concatenation only. 68131 * @param sanitizer An optional sanitizer function 68132 * @returns itself, so that it may be chained. 68133 * @codeGenApi 68134 */ 68135 68136 68137function ɵɵattributeInterpolate4(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, suffix, sanitizer, namespace) { 68138 const lView = getLView(); 68139 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix); 68140 68141 if (interpolatedValue !== NO_CHANGE) { 68142 const tNode = getSelectedTNode(); 68143 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace); 68144 ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 4, prefix, i0, i1, i2, suffix); 68145 } 68146 68147 return ɵɵattributeInterpolate4; 68148} 68149/** 68150 * 68151 * Update an interpolated attribute on an element with 5 bound values surrounded by text. 68152 * 68153 * Used when the value passed to a property has 5 interpolated values in it: 68154 * 68155 * ```html 68156 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div> 68157 * ``` 68158 * 68159 * Its compiled representation is:: 68160 * 68161 * ```ts 68162 * ɵɵattributeInterpolate5( 68163 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix'); 68164 * ``` 68165 * 68166 * @param attrName The name of the attribute to update 68167 * @param prefix Static value used for concatenation only. 68168 * @param v0 Value checked for change. 68169 * @param i0 Static value used for concatenation only. 68170 * @param v1 Value checked for change. 68171 * @param i1 Static value used for concatenation only. 68172 * @param v2 Value checked for change. 68173 * @param i2 Static value used for concatenation only. 68174 * @param v3 Value checked for change. 68175 * @param i3 Static value used for concatenation only. 68176 * @param v4 Value checked for change. 68177 * @param suffix Static value used for concatenation only. 68178 * @param sanitizer An optional sanitizer function 68179 * @returns itself, so that it may be chained. 68180 * @codeGenApi 68181 */ 68182 68183 68184function ɵɵattributeInterpolate5(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix, sanitizer, namespace) { 68185 const lView = getLView(); 68186 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix); 68187 68188 if (interpolatedValue !== NO_CHANGE) { 68189 const tNode = getSelectedTNode(); 68190 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace); 68191 ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 5, prefix, i0, i1, i2, i3, suffix); 68192 } 68193 68194 return ɵɵattributeInterpolate5; 68195} 68196/** 68197 * 68198 * Update an interpolated attribute on an element with 6 bound values surrounded by text. 68199 * 68200 * Used when the value passed to a property has 6 interpolated values in it: 68201 * 68202 * ```html 68203 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div> 68204 * ``` 68205 * 68206 * Its compiled representation is:: 68207 * 68208 * ```ts 68209 * ɵɵattributeInterpolate6( 68210 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix'); 68211 * ``` 68212 * 68213 * @param attrName The name of the attribute to update 68214 * @param prefix Static value used for concatenation only. 68215 * @param v0 Value checked for change. 68216 * @param i0 Static value used for concatenation only. 68217 * @param v1 Value checked for change. 68218 * @param i1 Static value used for concatenation only. 68219 * @param v2 Value checked for change. 68220 * @param i2 Static value used for concatenation only. 68221 * @param v3 Value checked for change. 68222 * @param i3 Static value used for concatenation only. 68223 * @param v4 Value checked for change. 68224 * @param i4 Static value used for concatenation only. 68225 * @param v5 Value checked for change. 68226 * @param suffix Static value used for concatenation only. 68227 * @param sanitizer An optional sanitizer function 68228 * @returns itself, so that it may be chained. 68229 * @codeGenApi 68230 */ 68231 68232 68233function ɵɵattributeInterpolate6(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix, sanitizer, namespace) { 68234 const lView = getLView(); 68235 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix); 68236 68237 if (interpolatedValue !== NO_CHANGE) { 68238 const tNode = getSelectedTNode(); 68239 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace); 68240 ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 6, prefix, i0, i1, i2, i3, i4, suffix
vendor: 13,750 bytes, lines 68240-68624
68240); 68241 } 68242 68243 return ɵɵattributeInterpolate6; 68244} 68245/** 68246 * 68247 * Update an interpolated attribute on an element with 7 bound values surrounded by text. 68248 * 68249 * Used when the value passed to a property has 7 interpolated values in it: 68250 * 68251 * ```html 68252 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div> 68253 * ``` 68254 * 68255 * Its compiled representation is:: 68256 * 68257 * ```ts 68258 * ɵɵattributeInterpolate7( 68259 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix'); 68260 * ``` 68261 * 68262 * @param attrName The name of the attribute to update 68263 * @param prefix Static value used for concatenation only. 68264 * @param v0 Value checked for change. 68265 * @param i0 Static value used for concatenation only. 68266 * @param v1 Value checked for change. 68267 * @param i1 Static value used for concatenation only. 68268 * @param v2 Value checked for change. 68269 * @param i2 Static value used for concatenation only. 68270 * @param v3 Value checked for change. 68271 * @param i3 Static value used for concatenation only. 68272 * @param v4 Value checked for change. 68273 * @param i4 Static value used for concatenation only. 68274 * @param v5 Value checked for change. 68275 * @param i5 Static value used for concatenation only. 68276 * @param v6 Value checked for change. 68277 * @param suffix Static value used for concatenation only. 68278 * @param sanitizer An optional sanitizer function 68279 * @returns itself, so that it may be chained. 68280 * @codeGenApi 68281 */ 68282 68283 68284function ɵɵattributeInterpolate7(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix, sanitizer, namespace) { 68285 const lView = getLView(); 68286 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix); 68287 68288 if (interpolatedValue !== NO_CHANGE) { 68289 const tNode = getSelectedTNode(); 68290 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace); 68291 ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 7, prefix, i0, i1, i2, i3, i4, i5, suffix); 68292 } 68293 68294 return ɵɵattributeInterpolate7; 68295} 68296/** 68297 * 68298 * Update an interpolated attribute on an element with 8 bound values surrounded by text. 68299 * 68300 * Used when the value passed to a property has 8 interpolated values in it: 68301 * 68302 * ```html 68303 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div> 68304 * ``` 68305 * 68306 * Its compiled representation is:: 68307 * 68308 * ```ts 68309 * ɵɵattributeInterpolate8( 68310 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix'); 68311 * ``` 68312 * 68313 * @param attrName The name of the attribute to update 68314 * @param prefix Static value used for concatenation only. 68315 * @param v0 Value checked for change. 68316 * @param i0 Static value used for concatenation only. 68317 * @param v1 Value checked for change. 68318 * @param i1 Static value used for concatenation only. 68319 * @param v2 Value checked for change. 68320 * @param i2 Static value used for concatenation only. 68321 * @param v3 Value checked for change. 68322 * @param i3 Static value used for concatenation only. 68323 * @param v4 Value checked for change. 68324 * @param i4 Static value used for concatenation only. 68325 * @param v5 Value checked for change. 68326 * @param i5 Static value used for concatenation only. 68327 * @param v6 Value checked for change. 68328 * @param i6 Static value used for concatenation only. 68329 * @param v7 Value checked for change. 68330 * @param suffix Static value used for concatenation only. 68331 * @param sanitizer An optional sanitizer function 68332 * @returns itself, so that it may be chained. 68333 * @codeGenApi 68334 */ 68335 68336 68337function ɵɵattributeInterpolate8(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix, sanitizer, namespace) { 68338 const lView = getLView(); 68339 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix); 68340 68341 if (interpolatedValue !== NO_CHANGE) { 68342 const tNode = getSelectedTNode(); 68343 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace); 68344 ngDevMode && storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 8, prefix, i0, i1, i2, i3, i4, i5, i6, suffix); 68345 } 68346 68347 return ɵɵattributeInterpolate8; 68348} 68349/** 68350 * Update an interpolated attribute on an element with 9 or more bound values surrounded by text. 68351 * 68352 * Used when the number of interpolated values exceeds 8. 68353 * 68354 * ```html 68355 * <div 68356 * title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"></div> 68357 * ``` 68358 * 68359 * Its compiled representation is:: 68360 * 68361 * ```ts 68362 * ɵɵattributeInterpolateV( 68363 * 'title', ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9, 68364 * 'suffix']); 68365 * ``` 68366 * 68367 * @param attrName The name of the attribute to update. 68368 * @param values The collection of values and the strings in-between those values, beginning with 68369 * a string prefix and ending with a string suffix. 68370 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`) 68371 * @param sanitizer An optional sanitizer function 68372 * @returns itself, so that it may be chained. 68373 * @codeGenApi 68374 */ 68375 68376 68377function ɵɵattributeInterpolateV(attrName, values, sanitizer, namespace) { 68378 const lView = getLView(); 68379 const interpolated = interpolationV(lView, values); 68380 68381 if (interpolated !== NO_CHANGE) { 68382 const tNode = getSelectedTNode(); 68383 elementAttributeInternal(tNode, lView, attrName, interpolated, sanitizer, namespace); 68384 68385 if (ngDevMode) { 68386 const interpolationInBetween = [values[0]]; // prefix 68387 68388 for (let i = 2; i < values.length; i += 2) { 68389 interpolationInBetween.push(values[i]); 68390 } 68391 68392 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - interpolationInBetween.length + 1, ...interpolationInBetween); 68393 } 68394 } 68395 68396 return ɵɵattributeInterpolateV; 68397} 68398/** 68399 * @license 68400 * Copyright Google LLC All Rights Reserved. 68401 * 68402 * Use of this source code is governed by an MIT-style license that can be 68403 * found in the LICENSE file at https://angular.io/license 68404 */ 68405 68406/** 68407 * Synchronously perform change detection on a component (and possibly its sub-components). 68408 * 68409 * This function triggers change detection in a synchronous way on a component. 68410 * 68411 * @param component The component which the change detection should be performed on. 68412 */ 68413 68414 68415function detectChanges(component) { 68416 const view = getComponentViewByInstance(component); 68417 detectChangesInternal(view[TVIEW], view, component); 68418} 68419/** 68420 * @license 68421 * Copyright Google LLC All Rights Reserved. 68422 * 68423 * Use of this source code is governed by an MIT-style license that can be 68424 * found in the LICENSE file at https://angular.io/license 68425 */ 68426 68427 68428function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) { 68429 ngDevMode && assertFirstCreatePass(tView); 68430 ngDevMode && ngDevMode.firstCreatePass++; 68431 const tViewConsts = tView.consts; // TODO(pk): refactor getOrCreateTNode to have the "create" only version 68432 68433 const tNode = getOrCreateTNode(tView, index, 4 68434 /* TNodeType.Container */ 68435 , tagName || null, getConstant(tViewConsts, attrsIndex)); 68436 resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex)); 68437 registerPostOrderHooks(tView, tNode); 68438 const embeddedTView = tNode.tViews = createTView(2 68439 /* TViewType.Embedded */ 68440 , tNode, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts); 68441 68442 if (tView.queries !== null) { 68443 tView.queries.template(tView, tNode); 68444 embeddedTView.queries = tView.queries.embeddedTView(tNode); 68445 } 68446 68447 return tNode; 68448} 68449/** 68450 * Creates an LContainer for an ng-template (dynamically-inserted view), e.g. 68451 * 68452 * <ng-template #foo> 68453 * <div></div> 68454 * </ng-template> 68455 * 68456 * @param index The index of the container in the data array 68457 * @param templateFn Inline template 68458 * @param decls The number of nodes, local refs, and pipes for this template 68459 * @param vars The number of bindings for this template 68460 * @param tagName The name of the container element, if applicable 68461 * @param attrsIndex Index of template attributes in the `consts` array. 68462 * @param localRefs Index of the local references in the `consts` array. 68463 * @param localRefExtractor A function which extracts local-refs values from the template. 68464 * Defaults to the current element associated with the local-ref. 68465 * 68466 * @codeGenApi 68467 */ 68468 68469 68470function ɵɵtemplate(index, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex, localRefExtractor) { 68471 const lView = getLView(); 68472 const tView = getTView(); 68473 const adjustedIndex = index + HEADER_OFFSET; 68474 const tNode = tView.firstCreatePass ? templateFirstCreatePass(adjustedIndex, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) : tView.data[adjustedIndex]; 68475 setCurrentTNode(tNode, false); 68476 const comment = lView[RENDERER].createComment(ngDevMode ? 'container' : ''); 68477 appendChild(tView, lView, comment, tNode); 68478 attachPatchData(comment, lView); 68479 addToViewTree(lView, lView[adjustedIndex] = createLContainer(comment, lView, comment, tNode)); 68480 68481 if (isDirectiveHost(tNode)) { 68482 createDirectivesInstances(tView, lView, tNode); 68483 } 68484 68485 if (localRefsIndex != null) { 68486 saveResolvedLocalsInData(lView, tNode, localRefExtractor); 68487 } 68488} 68489/** 68490 * @license 68491 * Copyright Google LLC All Rights Reserved. 68492 * 68493 * Use of this source code is governed by an MIT-style license that can be 68494 * found in the LICENSE file at https://angular.io/license 68495 */ 68496 68497/** Store a value in the `data` at a given `index`. */ 68498 68499 68500function store(tView, lView, index, value) { 68501 // We don't store any static data for local variables, so the first time 68502 // we see the template, we should store as null to avoid a sparse array 68503 if (index >= tView.data.length) { 68504 tView.data[index] = null; 68505 tView.blueprint[index] = null; 68506 } 68507 68508 lView[index] = value; 68509} 68510/** 68511 * Retrieves a local reference from the current contextViewData. 68512 * 68513 * If the reference to retrieve is in a parent view, this instruction is used in conjunction 68514 * with a nextContext() call, which walks up the tree and updates the contextViewData instance. 68515 * 68516 * @param index The index of the local ref in contextViewData. 68517 * 68518 * @codeGenApi 68519 */ 68520 68521 68522function ɵɵreference(index) { 68523 const contextLView = getContextLView(); 68524 return load(contextLView, HEADER_OFFSET + index); 68525} 68526/** 68527 * @license 68528 * Copyright Google LLC All Rights Reserved. 68529 * 68530 * Use of this source code is governed by an MIT-style license that can be 68531 * found in the LICENSE file at https://angular.io/license 68532 */ 68533 68534/** 68535 * Update a property on a selected element. 68536 * 68537 * Operates on the element selected by index via the {@link select} instruction. 68538 * 68539 * If the property name also exists as an input property on one of the element's directives, 68540 * the component property will be set instead of the element property. This check must 68541 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled 68542 * 68543 * @param propName Name of property. Because it is going to DOM, this is not subject to 68544 * renaming as part of minification. 68545 * @param value New value to write. 68546 * @param sanitizer An optional function used to sanitize the value. 68547 * @returns This function returns itself so that it may be chained 68548 * (e.g. `property('name', ctx.name)('title', ctx.title)`) 68549 * 68550 * @codeGenApi 68551 */ 68552 68553 68554function ɵɵproperty(propName, value, sanitizer) { 68555 const lView = getLView(); 68556 const bindingIndex = nextBindingIndex(); 68557 68558 if (bindingUpdated(lView, bindingIndex, value)) { 68559 const tView = getTView(); 68560 const tNode = getSelectedTNode(); 68561 elementPropertyInternal(tView, tNode, lView, propName, value, lView[RENDERER], sanitizer, false); 68562 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex); 68563 } 68564 68565 return ɵɵproperty; 68566} 68567/** 68568 * Given `<div style="..." my-dir>` and `MyDir` with `@Input('style')` we need to write to 68569 * directive input. 68570 */ 68571 68572 68573function setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased) { 68574 const inputs = tNode.inputs; 68575 const property = isClassBased ? 'class' : 'style'; // We support both 'class' and `className` hence the fallback. 68576 68577 setInputsForProperty(tView, lView, inputs[property], property, value); 68578} 68579/** 68580 * @license 68581 * Copyright Google LLC All Rights Reserved. 68582 * 68583 * Use of this source code is governed by an MIT-style license that can be 68584 * found in the LICENSE file at https://angular.io/license 68585 */ 68586 68587 68588function elementStartFirstCreatePass(index, tView, lView, native, name, attrsIndex, localRefsIndex) { 68589 ngDevMode && assertFirstCreatePass(tView); 68590 ngDevMode && ngDevMode.firstCreatePass++; 68591 const tViewConsts = tView.consts; 68592 const attrs = getConstant(tViewConsts, attrsIndex); 68593 const tNode = getOrCreateTNode(tView, index, 2 68594 /* TNodeType.Element */ 68595 , name, attrs); 68596 const hasDirectives = resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex)); 68597 68598 if (ngDevMode) { 68599 validateElementIsKnown(native, lView, tNode.value, tView.schemas, hasDirectives); 68600 } 68601 68602 if (tNode.attrs !== null) { 68603 computeStaticStyling(tNode, tNode.attrs, false); 68604 } 68605 68606 if (tNode.mergedAttrs !== null) { 68607 computeStaticStyling(tNode, tNode.mergedAttrs, true); 68608 } 68609 68610 if (tView.queries !== null) { 68611 tView.queries.elementStart(tView, tNode); 68612 } 68613 68614 return tNode; 68615} 68616/** 68617 * Create DOM element. The instruction must later be followed by `elementEnd()` call. 68618 * 68619 * @param index Index of the element in the LView array 68620 * @param name Name of the DOM Node 68621 * @param attrsIndex Index of the element's attributes in the `consts` array. 68622 * @param localRefsIndex Index of the element's local references in the `consts` array. 68623 * @returns This function returns itself so that it may be chained. 68624 *
68625 * Attributes and localRefs are passed as an array of strings where elements with an even index 68626 * hold an attribute name and elements with an odd index hold an attribute value, ex.: 68627 * ['id', 'warning5', 'class', 'alert'] 68628 * 68629 * @codeGenApi 68630 */ 68631 68632 68633function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) { 68634 const lView = getLView(); 68635 const tView = getTView(); 68636 const adjustedIndex = HEADER_OFFSET + index; 68637 ngDevMode && assertEqual(getBindingIndex(), tView.bindingStartIndex, 'elements should be created before any bindings'); 68638 ngDevMode && assertIndexInRange(lView, adjustedIndex); 68639 const renderer = lView[RENDERER]; 68640 const native = lView[adjustedIndex] = createElementNode(renderer, name, getNamespace$1()); 68641 const tNode = tView.firstCreatePass ? elementStartFirstCreatePass(adjustedIndex, tView, lView, native, name, attrsIndex, localRefsIndex) : tView.data[adjustedIndex]; 68642 setCurrentTNode(tNode, true); 68643 const mergedAttrs = tNode.mergedAttrs; 68644 68645 if (mergedAttrs !== null) { 68646 setUpAttributes(renderer, native, mergedAttrs); 68647 } 68648 68649 const classes = tNode.classes; 68650 68651 if (classes !== null) { 68652 writeDirectClass(renderer, native, classes); 68653 } 68654 68655 const styles = tNode.styles; 68656 68657 if (styles !== null) { 68658 writeDirectStyle(renderer, native, styles); 68659 } 68660 68661 if ((tNode.flags & 64 68662 /* TNodeFlags.isDetached */ 68663 ) !== 64 68664 /* TNodeFlags.isDetached */ 68665 ) { 68666 // In the i18n case, the translation may have removed this element, so only add it if it is not 68667 // detached. See `TNodeType.Placeholder` and `LFrame.inI18n` for more context. 68668 appendChild(tView, lView, native, tNode); 68669 } // any immediate children of a component or template container must be pre-emptively 68670 // monkey-patched with the component view data so that the element can be inspected 68671 // later on using any element discovery utility methods (see `element_discovery.ts`) 68672 68673 68674 if (getElementDepthCount() === 0) { 68675 attachPatchData(native, lView); 68676 } 68677 68678 increaseElementDepthCount(); 68679 68680 if (isDirectiveHost(tNode)) { 68681 createDirectivesInstances(tView, lView, tNode); 68682 executeContentQueries(tView, tNode, lView); 68683 } 68684 68685 if (localRefsIndex !== null) { 68686 saveResolvedLocalsInData(lView, tNode); 68687 } 68688 68689 return ɵɵelementStart; 68690} 68691/** 68692 * Mark the end of the element. 68693 * @returns This function returns itself so that it may be chained. 68694 * 68695 * @codeGenApi 68696 */ 68697 68698 68699function ɵɵelementEnd() { 68700 let currentTNode = getCurrentTNode(); 68701 ngDevMode && assertDefined(currentTNode, 'No parent node to close.'); 68702 68703 if (isCurrentTNodeParent()) { 68704 setCurrentTNodeAsNotParent(); 68705 } else { 68706 ngDevMode && assertHasParent(getCurrentTNode()); 68707 currentTNode = currentTNode.parent; 68708 setCurrentTNode(currentTNode, false); 68709 } 68710 68711 const tNode = currentTNode; 68712 ngDevMode && assertTNodeType(tNode, 3 68713 /* TNodeType.AnyRNode */ 68714 ); 68715 decreaseElementDepthCount(); 68716 const tView = getTView(); 68717 68718 if (tView.firstCreatePass) { 68719 registerPostOrderHooks(tView, currentTNode); 68720 68721 if (isContentQueryHost(currentTNode)) { 68722 tView.queries.elementEnd(currentTNode); 68723 } 68724 } 68725 68726 if (tNode.classesWithoutHost != null && hasClassInput(tNode)) { 68727 setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.classesWithoutHost, true); 68728 } 68729 68730 if (tNode.stylesWithoutHost != null && hasStyleInput(tNode)) { 68731 setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.stylesWithoutHost, false); 68732 } 68733 68734 return ɵɵelementEnd; 68735} 68736/** 68737 * Creates an empty element using {@link elementStart} and {@link elementEnd} 68738 * 68739 * @param index Index of the element in the data array 68740 * @param name Name of the DOM Node 68741 * @param attrsIndex Index of the element's attributes in the `consts` array. 68742 * @param localRefsIndex Index of the element's local references in the `consts` array. 68743 * @returns This function returns itself so that it may be chained. 68744 * 68745 * @codeGenApi 68746 */ 68747 68748 68749function ɵɵelement(index, name, attrsIndex, localRefsIndex) { 68750 ɵɵelementStart(index, name, attrsIndex, localRefsIndex); 68751 ɵɵelementEnd(); 68752 return ɵɵelement; 68753} 68754/** 68755 * @license 68756 * Copyright Google LLC All Rights Reserved. 68757 * 68758 * Use of this source code is governed by an MIT-style license that can be 68759 * found in the LICENSE file at https://angular.io/license 68760 */ 68761 68762 68763function elementContainerStartFirstCreatePass(index, tView, lView, attrsIndex, localRefsIndex) { 68764 ngDevMode && ngDevMode.firstCreatePass++; 68765 const tViewConsts = tView.consts; 68766 const attrs = getConstant(tViewConsts, attrsIndex); 68767 const tNode = getOrCreateTNode(tView, index, 8 68768 /* TNodeType.ElementContainer */ 68769 , 'ng-container', attrs); // While ng-container doesn't necessarily support styling, we use the style context to identify 68770 // and execute directives on the ng-container. 68771 68772 if (attrs !== null) { 68773 computeStaticStyling(tNode, attrs, true); 68774 } 68775 68776 const localRefs = getConstant(tViewConsts, localRefsIndex); 68777 resolveDirectives(tView, lView, tNode, localRefs); 68778 68779 if (tView.queries !== null) { 68780 tView.queries.elementStart(tView, tNode); 68781 } 68782 68783 return tNode; 68784} 68785/** 68786 * Creates a logical container for other nodes (<ng-container>) backed by a comment node in the DOM. 68787 * The instruction must later be followed by `elementContainerEnd()` call. 68788 * 68789 * @param index Index of the element in the LView array 68790 * @param attrsIndex Index of the container attributes in the `consts` array. 68791 * @param localRefsIndex Index of the container's local references in the `consts` array. 68792 * @returns This function returns itself so that it may be chained. 68793 * 68794 * Even if this instruction accepts a set of attributes no actual attribute values are propagated to 68795 * the DOM (as a comment node can't have attributes). Attributes are here only for directive 68796 * matching purposes and setting initial inputs of directives. 68797 * 68798 * @codeGenApi 68799 */ 68800 68801 68802function ɵɵelementContainerStart(index, attrsIndex, localRefsIndex) { 68803 const lView = getLView(); 68804 const tView = getTView(); 68805 const adjustedIndex = index + HEADER_OFFSET; 68806 ngDevMode && assertIndexInRange(lView, adjustedIndex); 68807 ngDevMode && assertEqual(getBindingIndex(), tView.bindingStartIndex, 'element containers should be created before any bindings'); 68808 const tNode = tView.firstCreatePass ? elementContainerStartFirstCreatePass(adjustedIndex, tView, lView, attrsIndex, localRefsIndex) : tView.data[adjustedIndex]; 68809 setCurrentTNode(tNode, true); 68810 ngDevMode && ngDevMode.rendererCreateComment++; 68811 const native = lView[adjustedIndex] = lView[RENDERER].createComment(ngDevMode ? 'ng-container' : ''); 68812 appendChild(tView, lView, native, tNode);
vendor: 15,556 bytes, lines 68813-69216
68813 attachPatchData(native, lView); 68814 68815 if (isDirectiveHost(tNode)) { 68816 createDirectivesInstances(tView, lView, tNode); 68817 executeContentQueries(tView, tNode, lView); 68818 } 68819 68820 if (localRefsIndex != null) { 68821 saveResolvedLocalsInData(lView, tNode); 68822 } 68823 68824 return ɵɵelementContainerStart; 68825} 68826/** 68827 * Mark the end of the <ng-container>. 68828 * @returns This function returns itself so that it may be chained. 68829 * 68830 * @codeGenApi 68831 */ 68832 68833 68834function ɵɵelementContainerEnd() { 68835 let currentTNode = getCurrentTNode(); 68836 const tView = getTView(); 68837 68838 if (isCurrentTNodeParent()) { 68839 setCurrentTNodeAsNotParent(); 68840 } else { 68841 ngDevMode && assertHasParent(currentTNode); 68842 currentTNode = currentTNode.parent; 68843 setCurrentTNode(currentTNode, false); 68844 } 68845 68846 ngDevMode && assertTNodeType(currentTNode, 8 68847 /* TNodeType.ElementContainer */ 68848 ); 68849 68850 if (tView.firstCreatePass) { 68851 registerPostOrderHooks(tView, currentTNode); 68852 68853 if (isContentQueryHost(currentTNode)) { 68854 tView.queries.elementEnd(currentTNode); 68855 } 68856 } 68857 68858 return ɵɵelementContainerEnd; 68859} 68860/** 68861 * Creates an empty logical container using {@link elementContainerStart} 68862 * and {@link elementContainerEnd} 68863 * 68864 * @param index Index of the element in the LView array 68865 * @param attrsIndex Index of the container attributes in the `consts` array. 68866 * @param localRefsIndex Index of the container's local references in the `consts` array. 68867 * @returns This function returns itself so that it may be chained. 68868 * 68869 * @codeGenApi 68870 */ 68871 68872 68873function ɵɵelementContainer(index, attrsIndex, localRefsIndex) { 68874 ɵɵelementContainerStart(index, attrsIndex, localRefsIndex); 68875 ɵɵelementContainerEnd(); 68876 return ɵɵelementContainer; 68877} 68878/** 68879 * Returns the current OpaqueViewState instance. 68880 * 68881 * Used in conjunction with the restoreView() instruction to save a snapshot 68882 * of the current view and restore it when listeners are invoked. This allows 68883 * walking the declaration view tree in listeners to get vars from parent views. 68884 * 68885 * @codeGenApi 68886 */ 68887 68888 68889function ɵɵgetCurrentView() { 68890 return getLView(); 68891} 68892/** 68893 * @license 68894 * Copyright Google LLC All Rights Reserved. 68895 * 68896 * Use of this source code is governed by an MIT-style license that can be 68897 * found in the LICENSE file at https://angular.io/license 68898 */ 68899 68900/** 68901 * Determine if the argument is shaped like a Promise 68902 */ 68903 68904 68905function isPromise(obj) { 68906 // allow any Promise/A+ compliant thenable. 68907 // It's up to the caller to ensure that obj.then conforms to the spec 68908 return !!obj && typeof obj.then === 'function'; 68909} 68910/** 68911 * Determine if the argument is a Subscribable 68912 */ 68913 68914 68915function isSubscribable(obj) { 68916 return !!obj && typeof obj.subscribe === 'function'; 68917} 68918/** 68919 * Determine if the argument is an Observable 68920 * 68921 * Strictly this tests that the `obj` is `Subscribable`, since `Observable` 68922 * types need additional methods, such as `lift()`. But it is adequate for our 68923 * needs since within the Angular framework code we only ever need to use the 68924 * `subscribe()` method, and RxJS has mechanisms to wrap `Subscribable` objects 68925 * into `Observable` as needed. 68926 */ 68927 68928 68929const isObservable = isSubscribable; 68930/** 68931 * @license 68932 * Copyright Google LLC All Rights Reserved. 68933 * 68934 * Use of this source code is governed by an MIT-style license that can be 68935 * found in the LICENSE file at https://angular.io/license 68936 */ 68937 68938/** 68939 * Adds an event listener to the current node. 68940 * 68941 * If an output exists on one of the node's directives, it also subscribes to the output 68942 * and saves the subscription for later cleanup. 68943 * 68944 * @param eventName Name of the event 68945 * @param listenerFn The function to be called when event emits 68946 * @param useCapture Whether or not to use capture in event listener 68947 * @param eventTargetResolver Function that returns global target information in case this listener 68948 * should be attached to a global object like window, document or body 68949 * 68950 * @codeGenApi 68951 */ 68952 68953function ɵɵlistener(eventName, listenerFn, useCapture, eventTargetResolver) { 68954 const lView = getLView(); 68955 const tView = getTView(); 68956 const tNode = getCurrentTNode(); 68957 listenerInternal(tView, lView, lView[RENDERER], tNode, eventName, listenerFn, !!useCapture, eventTargetResolver); 68958 return ɵɵlistener; 68959} 68960/** 68961 * Registers a synthetic host listener (e.g. `(@foo.start)`) on a component or directive. 68962 * 68963 * This instruction is for compatibility purposes and is designed to ensure that a 68964 * synthetic host listener (e.g. `@HostListener('@foo.start')`) properly gets rendered 68965 * in the component's renderer. Normally all host listeners are evaluated with the 68966 * parent component's renderer, but, in the case of animation @triggers, they need 68967 * to be evaluated with the sub component's renderer (because that's where the 68968 * animation triggers are defined). 68969 * 68970 * Do not use this instruction as a replacement for `listener`. This instruction 68971 * only exists to ensure compatibility with the ViewEngine's host binding behavior. 68972 * 68973 * @param eventName Name of the event 68974 * @param listenerFn The function to be called when event emits 68975 * @param useCapture Whether or not to use capture in event listener 68976 * @param eventTargetResolver Function that returns global target information in case this listener 68977 * should be attached to a global object like window, document or body 68978 * 68979 * @codeGenApi 68980 */ 68981 68982 68983function ɵɵsyntheticHostListener(eventName, listenerFn) { 68984 const tNode = getCurrentTNode(); 68985 const lView = getLView(); 68986 const tView = getTView(); 68987 const currentDef = getCurrentDirectiveDef(tView.data); 68988 const renderer = loadComponentRenderer(currentDef, tNode, lView); 68989 listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn, false); 68990 return ɵɵsyntheticHostListener; 68991} 68992/** 68993 * A utility function that checks if a given element has already an event handler registered for an 68994 * event with a specified name. The TView.cleanup data structure is used to find out which events 68995 * are registered for a given element. 68996 */ 68997 68998 68999function findExistingListener(tView, lView, eventName, tNodeIdx) { 69000 const tCleanup = tView.cleanup; 69001 69002 if (tCleanup != null) { 69003 for (let i = 0; i < tCleanup.length - 1; i += 2) { 69004 const cleanupEventName = tCleanup[i]; 69005 69006 if (cleanupEventName === eventName && tCleanup[i + 1] === tNodeIdx) { 69007 // We have found a matching event name on the same node but it might not have been 69008 // registered yet, so we must explicitly verify entries in the LView cleanup data 69009 // structures. 69010 const lCleanup = lView[CLEANUP]; 69011 const listenerIdxInLCleanup = tCleanup[i + 2]; 69012 return lCleanup.length > listenerIdxInLCleanup ? lCleanup[listenerIdxInLCleanup] : null; 69013 } // TView.cleanup can have a mix of 4-elements entries (for event handler cleanups) or 69014 // 2-element entries (for directive and queries destroy hooks). As such we can encounter 69015 // blocks of 4 or 2 items in the tView.cleanup and this is why we iterate over 2 elements 69016 // first and jump another 2 elements if we detect listeners cleanup (4 elements). Also check 69017 // documentation of TView.cleanup for more details of this data structure layout. 69018 69019 69020 if (typeof cleanupEventName === 'string') { 69021 i += 2; 69022 } 69023 } 69024 } 69025 69026 return null; 69027} 69028 69029function listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn, useCapture, eventTargetResolver) { 69030 const isTNodeDirectiveHost = isDirectiveHost(tNode); 69031 const firstCreatePass = tView.firstCreatePass; 69032 const tCleanup = firstCreatePass && getOrCreateTViewCleanup(tView); 69033 const context = lView[CONTEXT]; // When the ɵɵlistener instruction was generated and is executed we know that there is either a 69034 // native listener or a directive output on this element. As such we we know that we will have to 69035 // register a listener and store its cleanup function on LView. 69036 69037 const lCleanup = getOrCreateLViewCleanup(lView); 69038 ngDevMode && assertTNodeType(tNode, 3 69039 /* TNodeType.AnyRNode */ 69040 | 12 69041 /* TNodeType.AnyContainer */ 69042 ); 69043 let processOutputs = true; // Adding a native event listener is applicable when: 69044 // - The corresponding TNode represents a DOM element. 69045 // - The event target has a resolver (usually resulting in a global object, 69046 // such as `window` or `document`). 69047 69048 if (tNode.type & 3 69049 /* TNodeType.AnyRNode */ 69050 || eventTargetResolver) { 69051 const native = getNativeByTNode(tNode, lView); 69052 const target = eventTargetResolver ? eventTargetResolver(native) : native; 69053 const lCleanupIndex = lCleanup.length; 69054 const idxOrTargetGetter = eventTargetResolver ? _lView => eventTargetResolver(unwrapRNode(_lView[tNode.index])) : tNode.index; // In order to match current behavior, native DOM event listeners must be added for all 69055 // events (including outputs). 69056 // There might be cases where multiple directives on the same element try to register an event 69057 // handler function for the same event. In this situation we want to avoid registration of 69058 // several native listeners as each registration would be intercepted by NgZone and 69059 // trigger change detection. This would mean that a single user action would result in several 69060 // change detections being invoked. To avoid this situation we want to have only one call to 69061 // native handler registration (for the same element and same type of event). 69062 // 69063 // In order to have just one native event handler in presence of multiple handler functions, 69064 // we just register a first handler function as a native event listener and then chain 69065 // (coalesce) other handler functions on top of the first native handler function. 69066 69067 let existingListener = null; // Please note that the coalescing described here doesn't happen for events specifying an 69068 // alternative target (ex. (document:click)) - this is to keep backward compatibility with the 69069 // view engine. 69070 // Also, we don't have to search for existing listeners is there are no directives 69071 // matching on a given node as we can't register multiple event handlers for the same event in 69072 // a template (this would mean having duplicate attributes). 69073 69074 if (!eventTargetResolver && isTNodeDirectiveHost) { 69075 existingListener = findExistingListener(tView, lView, eventName, tNode.index); 69076 } 69077 69078 if (existingListener !== null) { 69079 // Attach a new listener to coalesced listeners list, maintaining the order in which 69080 // listeners are registered. For performance reasons, we keep a reference to the last 69081 // listener in that list (in `__ngLastListenerFn__` field), so we can avoid going through 69082 // the entire set each time we need to add a new listener. 69083 const lastListenerFn = existingListener.__ngLastListenerFn__ || existingListener; 69084 lastListenerFn.__ngNextListenerFn__ = listenerFn; 69085 existingListener.__ngLastListenerFn__ = listenerFn; 69086 processOutputs = false; 69087 } else { 69088 listenerFn = wrapListener(tNode, lView, context, listenerFn, false 69089 /** preventDefault */ 69090 ); 69091 const cleanupFn = renderer.listen(target, eventName, listenerFn); 69092 ngDevMode && ngDevMode.rendererAddEventListener++; 69093 lCleanup.push(listenerFn, cleanupFn); 69094 tCleanup && tCleanup.push(eventName, idxOrTargetGetter, lCleanupIndex, lCleanupIndex + 1); 69095 } 69096 } else { 69097 // Even if there is no native listener to add, we still need to wrap the listener so that OnPush 69098 // ancestors are marked dirty when an event occurs. 69099 listenerFn = wrapListener(tNode, lView, context, listenerFn, false 69100 /** preventDefault */ 69101 ); 69102 } // subscribe to directive outputs 69103 69104 69105 const outputs = tNode.outputs; 69106 let props; 69107 69108 if (processOutputs && outputs !== null && (props = outputs[eventName])) { 69109 const propsLength = props.length; 69110 69111 if (propsLength) { 69112 for (let i = 0; i < propsLength; i += 2) { 69113 const index = props[i]; 69114 ngDevMode && assertIndexInRange(lView, index); 69115 const minifiedName = props[i + 1]; 69116 const directiveInstance = lView[index]; 69117 const output = directiveInstance[minifiedName]; 69118 69119 if (ngDevMode && !isObservable(output)) { 69120 throw new Error(`@Output ${minifiedName} not initialized in '${directiveInstance.constructor.name}'.`); 69121 } 69122 69123 const subscription = output.subscribe(listenerFn); 69124 const idx = lCleanup.length; 69125 lCleanup.push(listenerFn, subscription); 69126 tCleanup && tCleanup.push(eventName, tNode.index, idx, -(idx + 1)); 69127 } 69128 } 69129 } 69130} 69131 69132function executeListenerWithErrorHandling(lView, context, listenerFn, e) { 69133 try { 69134 profiler(6 69135 /* ProfilerEvent.OutputStart */ 69136 , context, listenerFn); // Only explicitly returning false from a listener should preventDefault 69137 69138 return listenerFn(e) !== false; 69139 } catch (error) { 69140 handleError(lView, error); 69141 return false; 69142 } finally { 69143 profiler(7 69144 /* ProfilerEvent.OutputEnd */ 69145 , context, listenerFn); 69146 } 69147} 69148/** 69149 * Wraps an event listener with a function that marks ancestors dirty and prevents default behavior, 69150 * if applicable. 69151 * 69152 * @param tNode The TNode associated with this listener 69153 * @param lView The LView that contains this listener 69154 * @param listenerFn The listener function to call 69155 * @param wrapWithPreventDefault Whether or not to prevent default behavior 69156 * (the procedural renderer does this already, so in those cases, we should skip) 69157 */ 69158 69159 69160function wrapListener(tNode, lView, context, listenerFn, wrapWithPreventDefault) { 69161 // Note: we are performing most of the work in the listener function itself 69162 // to optimize listener registration. 69163 return function wrapListenerIn_markDirtyAndPreventDefault(e) { 69164 // Ivy uses `Function` as a special token that allows us to unwrap the function 69165 // so that it can be invoked programmatically by `DebugNode.triggerEventHandler`. 69166 if (e === Function) { 69167 return listenerFn; 69168 } // In order to be backwards compatible with View Engine, events on component host nodes 69169 // must also mark the component view itself dirty (i.e. the view that it owns). 69170 69171 69172 const startView = tNode.flags & 2 69173 /* TNodeFlags.isComponentHost */ 69174 ? getComponentLViewByIndex(tNode.index, lView) : lView; 69175 markViewDirty(startView); 69176 let result = executeListenerWithErrorHandling(lView, context, listenerFn, e); // A just-invoked listener function might have coalesced listeners so we need to check for 69177 // their presence and invoke as needed. 69178 69179 let nextListenerFn = wrapListenerIn_markDirtyAndPreventDefault.__ngNextListenerFn__; 69180 69181 while (nextListenerFn) { 69182 // We should prevent default if any of the listeners explicitly return false 69183 result = executeListenerWithErrorHandling(lView, context, nextListenerFn, e) && result; 69184 nextListenerFn = nextListenerFn.__ngNextListenerFn__; 69185 } 69186 69187 if (wrapWithPreventDefault && result === false) { 69188 e.preventDefault(); // Necessary for legacy browsers that don't support preventDefault (e.g. IE) 69189 69190 e.returnValue = false; 69191 } 69192 69193 return result; 69194 }; 69195} 69196/** 69197 * @license 69198 * Copyright Google LLC All Rights Reserved. 69199 * 69200 * Use of this source code is governed by an MIT-style license that can be 69201 * found in the LICENSE file at https://angular.io/license 69202 */ 69203 69204/** 69205 * @license 69206 * Copyright Google LLC All Rights Reserved. 69207 * 69208 * Use of this source code is governed by an MIT-style license that can be 69209 * found in the LICENSE file at https://angular.io/license 69210 */ 69211 69212/** 69213 * Retrieves a context at the level specified and saves it as the global, contextViewData. 69214 * Will get the next level up if level is not specified. 69215 * 69216 * This is used to save contexts of parent views so they can be bound in embedded views, or
69217 * in conjunction with reference() to bind a ref from a parent view. 69218 * 69219 * @param level The relative level of the view from which to grab context compared to contextVewData 69220 * @returns context 69221 * 69222 * @codeGenApi 69223 */ 69224 69225 69226function ɵɵnextContext(level = 1) { 69227 return nextContextImpl(level); 69228} 69229/** 69230 * @license 69231 * Copyright Google LLC All Rights Reserved. 69232 * 69233 * Use of this source code is governed by an MIT-style license that can be 69234 * found in the LICENSE file at https://angular.io/license 69235 */ 69236 69237/** 69238 * Checks a given node against matching projection slots and returns the 69239 * determined slot index. Returns "null" if no slot matched the given node. 69240 * 69241 * This function takes into account the parsed ngProjectAs selector from the 69242 * node's attributes. If present, it will check whether the ngProjectAs selector 69243 * matches any of the projection slot selectors. 69244 */ 69245 69246 69247function matchingProjectionSlotIndex(tNode, projectionSlots) { 69248 let wildcardNgContentIndex = null; 69249 const ngProjectAsAttrVal = getProjectAsAttrValue(tNode); 69250 69251 for (let i = 0; i < projectionSlots.length; i++) { 69252 const slotValue = projectionSlots[i]; // The last wildcard projection slot should match all nodes which aren't matching 69253 // any selector. This is necessary to be backwards compatible with view engine. 69254 69255 if (slotValue === '*') { 69256 wildcardNgContentIndex = i; 69257 continue; 69258 } // If we ran into an `ngProjectAs` attribute, we should match its parsed selector 69259 // to the list of selectors, otherwise we fall back to matching against the node. 69260 69261 69262 if (ngProjectAsAttrVal === null ? isNodeMatchingSelectorList(tNode, slotValue, 69263 /* isProjectionMode */ 69264 true) : isSelectorInSelectorList(ngProjectAsAttrVal, slotValue)) { 69265 return i; // first matching selector "captures" a given node 69266 } 69267 } 69268 69269 return wildcardNgContentIndex; 69270} 69271/** 69272 * Instruction to distribute projectable nodes among <ng-content> occurrences in a given template. 69273 * It takes all the selectors from the entire component's template and decides where 69274 * each projected node belongs (it re-distributes nodes among "buckets" where each "bucket" is 69275 * backed by a selector). 69276 * 69277 * This function requires CSS selectors to be provided in 2 forms: parsed (by a compiler) and text, 69278 * un-parsed form. 69279 * 69280 * The parsed form is needed for efficient matching of a node against a given CSS selector. 69281 * The un-parsed, textual form is needed for support of the ngProjectAs attribute. 69282 * 69283 * Having a CSS selector in 2 different formats is not ideal, but alternatives have even more 69284 * drawbacks: 69285 * - having only a textual form would require runtime parsing of CSS selectors; 69286 * - we can't have only a parsed as we can't re-construct textual form from it (as entered by a 69287 * template author). 69288 * 69289 * @param projectionSlots? A collection of projection slots. A projection slot can be based 69290 * on a parsed CSS selectors or set to the wildcard selector ("*") in order to match 69291 * all nodes which do not match any selector. If not specified, a single wildcard 69292 * selector projection slot will be defined. 69293 * 69294 * @codeGenApi 69295 */ 69296 69297 69298function ɵɵprojectionDef(projectionSlots) { 69299 const componentNode = getLView()[DECLARATION_COMPONENT_VIEW][T_HOST]; 69300 69301 if (!componentNode.projection) { 69302 // If no explicit projection slots are defined, fall back to a single 69303 // projection slot with the wildcard selector. 69304 const numProjectionSlots = projectionSlots ? projectionSlots.length : 1; 69305 const projectionHeads = componentNode.projection = newArray(numProjectionSlots, null); 69306 const tails = projectionHeads.slice(); 69307 let componentChild = componentNode.child; 69308 69309 while (componentChild !== null) { 69310 const slotIndex = projectionSlots ? matchingProjectionSlotIndex(componentChild, projectionSlots) : 0; 69311 69312 if (slotIndex !== null) { 69313 if (tails[slotIndex]) { 69314 tails[slotIndex].projectionNext = componentChild; 69315 } else { 69316 projectionHeads[slotIndex] = componentChild; 69317 } 69318 69319 tails[slotIndex] = componentChild; 69320 } 69321 69322 componentChild = componentChild.next; 69323 } 69324 } 69325} 69326/** 69327 * Inserts previously re-distributed projected nodes. This instruction must be preceded by a call 69328 * to the projectionDef instruction. 69329 * 69330 * @param nodeIndex 69331 * @param selectorIndex: 69332 * - 0 when the selector is `*` (or unspecified as this is the default value), 69333 * - 1 based index of the selector from the {@link projectionDef} 69334 * 69335 * @codeGenApi 69336 */ 69337 69338 69339function ɵɵprojection(nodeIndex, selectorIndex = 0, attrs) { 69340 const lView = getLView(); 69341 const tView = getTView(); 69342 const tProjectionNode = getOrCreateTNode(tView, HEADER_OFFSET + nodeIndex, 16 69343 /* TNodeType.Projection */ 69344 , null, attrs || null); // We can't use viewData[HOST_NODE] because projection nodes can be nested in embedded views. 69345 69346 if (tProjectionNode.projection === null) tProjectionNode.projection = selectorIndex; // `<ng-content>` has no content 69347 69348 setCurrentTNodeAsNotParent(); 69349 69350 if ((tProjectionNode.flags & 64 69351 /* TNodeFlags.isDetached */ 69352 ) !== 64 69353 /* TNodeFlags.isDetached */ 69354 ) { 69355 // re-distribution of projectable nodes is stored on a component's view level 69356 applyProjection(tView, lView, tProjectionNode); 69357 } 69358} 69359/** 69360 * 69361 * Update an interpolated property on an element with a lone bound value 69362 * 69363 * Used when the value passed to a property has 1 interpolated value in it, an no additional text 69364 * surrounds that interpolated value: 69365 * 69366 * ```html 69367 * <div title="{{v0}}"></div> 69368 * ``` 69369 * 69370 * Its compiled representation is:: 69371 * 69372 * ```ts 69373 * ɵɵpropertyInterpolate('title', v0); 69374 * ``` 69375 * 69376 * If the property name also exists as an input property on one of the element's directives, 69377 * the component property will be set instead of the element property. This check must 69378 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled. 69379 * 69380 * @param propName The name of the property to update
69381 * @param prefix Static value used for concatenation only. 69382 * @param v0 Value checked for change. 69383 * @param suffix Static value used for concatenation only. 69384 * @param sanitizer An optional sanitizer function 69385 * @returns itself, so that it may be chained. 69386 * @codeGenApi 69387 */ 69388 69389 69390function ɵɵpropertyInterpolate(propName, v0, sanitizer) { 69391 ɵɵpropertyInterpolate1(propName, '', v0, '', sanitizer); 69392 return ɵɵpropertyInterpolate; 69393} 69394/** 69395 * 69396 * Update an interpolated property on an element with single bound value surrounded by text. 69397 * 69398 * Used when the value passed to a property has 1 interpolated value in it: 69399 * 69400 * ```html 69401 * <div title="prefix{{v0}}suffix"></div> 69402 * ``` 69403 * 69404 * Its compiled representation is:: 69405 * 69406 * ```ts 69407 * ɵɵpropertyInterpolate1('title', 'prefix', v0, 'suffix'); 69408 * ``` 69409 * 69410 * If the property name also exists as an input property on one of the element's directives, 69411 * the component property will be set instead of the element property. This check must 69412 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled. 69413 * 69414 * @param propName The name of the property to update 69415 * @param prefix Static value used for concatenation only. 69416 * @param v0 Value checked for change. 69417 * @param suffix Static value used for concatenation only. 69418 * @param sanitizer An optional sanitizer function 69419 * @returns itself, so that it may be chained. 69420 * @codeGenApi 69421 */ 69422 69423 69424function ɵɵpropertyInterpolate1(propName, prefix, v0, suffix, sanitizer) { 69425 const lView = getLView(); 69426 const interpolatedValue = interpolation1(lView, prefix, v0, suffix); 69427 69428 if (interpolatedValue !== NO_CHANGE) { 69429 const tView = getTView(); 69430 const tNode = getSelectedTNode(); 69431 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false); 69432 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 1, prefix, suffix); 69433 } 69434 69435 return ɵɵpropertyInterpolate1; 69436} 69437/** 69438 * 69439 * Update an interpolated property on an element with 2 bound values surrounded by text. 69440 * 69441 * Used when the value passed to a property has 2 interpolated values in it: 69442 * 69443 * ```html 69444 * <div title="prefix{{v0}}-{{v1}}suffix"></div> 69445 * ``` 69446 * 69447 * Its compiled representation is:: 69448 * 69449 * ```ts 69450 * ɵɵpropertyInterpolate2('title', 'prefix', v0, '-', v1, 'suffix'); 69451 * ``` 69452 * 69453 * If the property name also exists as an input property on one of the element's directives, 69454 * the component property will be set instead of the element property. This check must 69455 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled. 69456 * 69457 * @param propName The name of the property to update 69458 * @param prefix Static value used for concatenation only. 69459 * @param v0 Value checked for change. 69460 * @param i0 Static value used for concatenation only. 69461 * @param v1 Value checked for change. 69462 * @param suffix Static value used for concatenation only. 69463 * @param sanitizer An optional sanitizer function 69464 * @returns itself, so that it may be chained. 69465 * @codeGenApi 69466 */ 69467 69468 69469function ɵɵpropertyInterpolate2(propName, prefix, v0, i0, v1, suffix, sanitizer) { 69470 const lView = getLView(); 69471 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix); 69472 69473 if (interpolatedValue !== NO_CHANGE) { 69474 const tView = getTView(); 69475 const tNode = getSelectedTNode(); 69476 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false); 69477 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 2, prefix, i0, suffix); 69478 } 69479 69480 return ɵɵpropertyInterpolate2; 69481} 69482/** 69483 * 69484 * Update an interpolated property on an element with 3 bound values surrounded by text. 69485 * 69486 * Used when the value passed to a property has 3 interpolated values in it: 69487 * 69488 * ```html 69489 * <div title="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div> 69490 * ``` 69491 * 69492 * Its compiled representation is:: 69493 * 69494 * ```ts 69495 * ɵɵpropertyInterpolate3( 69496 * 'title', 'prefix', v0, '-', v1, '-', v2, 'suffix'); 69497 * ``` 69498 * 69499 * If the property name also exists as an input property on one of the element's directives, 69500 * the component property will be set instead of the element property. This check must 69501 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled. 69502 * 69503 * @param propName The name of the property to update
69504 * @param prefix Static value used for concatenation only. 69505 * @param v0 Value checked for change. 69506 * @param i0 Static value used for concatenation only. 69507 * @param v1 Value checked for change. 69508 * @param i1 Static value used for concatenation only. 69509 * @param v2 Value checked for change. 69510 * @param suffix Static value used for concatenation only. 69511 * @param sanitizer An optional sanitizer function 69512 * @returns itself, so that it may be chained. 69513 * @codeGenApi 69514 */ 69515 69516 69517function ɵɵpropertyInterpolate3(propName, prefix, v0, i0, v1, i1, v2, suffix, sanitizer) { 69518 const lView = getLView(); 69519 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix); 69520 69521 if (interpolatedValue !== NO_CHANGE) { 69522 const tView = getTView(); 69523 const tNode = getSelectedTNode(); 69524 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false); 69525 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 3, prefix, i0, i1, suffix); 69526 } 69527 69528 return ɵɵpropertyInterpolate3; 69529} 69530/** 69531 * 69532 * Update an interpolated property on an element with 4 bound values surrounded by text. 69533 * 69534 * Used when the value passed to a property has 4 interpolated values in it: 69535 * 69536 * ```html 69537 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div> 69538 * ``` 69539 * 69540 * Its compiled representation is:: 69541 * 69542 * ```ts 69543 * ɵɵpropertyInterpolate4( 69544 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix'); 69545 * ``` 69546 * 69547 * If the property name also exists as an input property on one of the element's directives, 69548 * the component property will be set instead of the element property. This check must 69549 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled. 69550 * 69551 * @param propName The name of the property to update 69552 * @param prefix Static value used for concatenation only. 69553 * @param v0 Value checked for change. 69554 * @param i0 Static value used for concatenation only. 69555 * @param v1 Value checked for change. 69556 * @param i1 Static value used for concatenation only. 69557 * @param v2 Value checked for change. 69558 * @param i2 Static value used for concatenation only. 69559 * @param v3 Value checked for change. 69560 * @param suffix Static value used for concatenation only. 69561 * @param sanitizer An optional sanitizer function 69562 * @returns itself, so that it may be chained. 69563 * @codeGenApi 69564 */ 69565 69566 69567function ɵɵpropertyInterpolate4(propName, prefix, v0, i0, v1, i1, v2, i2, v3, suffix, sanitizer) { 69568 const lView = getLView(); 69569 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix); 69570 69571 if (interpolatedValue !== NO_CHANGE) { 69572 const tView = getTView(); 69573 const tNode = getSelectedTNode(); 69574 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false); 69575 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 4, prefix, i0, i1, i2, suffix); 69576 } 69577 69578 return ɵɵpropertyInterpolate4; 69579} 69580/** 69581 * 69582 * Update an interpolated property on an element with 5 bound values surrounded by text. 69583 * 69584 * Used when the value passed to a property has 5 interpolated values in it: 69585 * 69586 * ```html 69587 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div> 69588 * ``` 69589 * 69590 * Its compiled representation is:: 69591 * 69592 * ```ts 69593 * ɵɵpropertyInterpolate5( 69594 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix'); 69595 * ``` 69596 * 69597 * If the property name also exists as an input property on one of the element's directives, 69598 * the component property will be set instead of the element property. This check must 69599 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled. 69600 * 69601 * @param propName The name of the property to update 69602 * @param prefix Static value used for concatenation only. 69603 * @param v0 Value checked for change. 69604 * @param i0 Static value used for concatenation only. 69605 * @param v1 Value checked for change. 69606 * @param i1 Static value used for concatenation only. 69607 * @param v2 Value checked for change. 69608 * @param i2 Static value used for concatenation only. 69609 * @param v3 Value checked for change.
69610 * @param i3 Static value used for concatenation only. 69611 * @param v4 Value checked for change. 69612 * @param suffix Static value used for concatenation only. 69613 * @param sanitizer An optional sanitizer function 69614 * @returns itself, so that it may be chained. 69615 * @codeGenApi 69616 */ 69617 69618 69619function ɵɵpropertyInterpolate5(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix, sanitizer) { 69620 const lView = getLView(); 69621 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix); 69622 69623 if (interpolatedValue !== NO_CHANGE) { 69624 const tView = getTView(); 69625 const tNode = getSelectedTNode(); 69626 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false); 69627 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 5, prefix, i0, i1, i2, i3, suffix); 69628 } 69629 69630 return ɵɵpropertyInterpolate5; 69631} 69632/** 69633 * 69634 * Update an interpolated property on an element with 6 bound values surrounded by text. 69635 * 69636 * Used when the value passed to a property has 6 interpolated values in it: 69637 * 69638 * ```html 69639 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div> 69640 * ``` 69641 * 69642 * Its compiled representation is:: 69643 * 69644 * ```ts 69645 * ɵɵpropertyInterpolate6( 69646 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix'); 69647 * ``` 69648 * 69649 * If the property name also exists as an input property on one of the element's directives, 69650 * the component property will be set instead of the element property. This check must 69651 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled. 69652 * 69653 * @param propName The name of the property to update 69654 * @param prefix Static value used for concatenation only. 69655 * @param v0 Value checked for change. 69656 * @param i0 Static value used for concatenation only. 69657 * @param v1 Value checked for change. 69658 * @param i1 Static value used for concatenation only. 69659 * @param v2 Value checked for change. 69660 * @param i2 Static value used for concatenation only. 69661 * @param v3 Value checked for change. 69662 * @param i3 Static value used for concatenation only. 69663 * @param v4 Value checked for change. 69664 * @param i4 Static value used for concatenation only. 69665 * @param v5 Value checked for change. 69666 * @param suffix Static value used for concatenation only. 69667 * @param sanitizer An optional sanitizer function 69668 * @returns itself, so that it may be chained. 69669 * @codeGenApi 69670 */ 69671 69672 69673function ɵɵpropertyInterpolate6(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix, sanitizer) { 69674 const lView = getLView(); 69675 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix); 69676 69677 if (interpolatedValue !== NO_CHANGE) { 69678 const tView = getTView(); 69679 const tNode = getSelectedTNode(); 69680 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false); 69681 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 6, prefix, i0, i1, i2, i3, i4, suffix); 69682 } 69683 69684 return ɵɵpropertyInterpolate6; 69685} 69686/** 69687 * 69688 * Update an interpolated property on an element with 7 bound values surrounded by text. 69689 * 69690 * Used when the value passed to a property has 7 interpolated values in it: 69691 * 69692 * ```html 69693 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div> 69694 * ``` 69695 * 69696 * Its compiled representation is:: 69697 * 69698 * ```ts 69699 * ɵɵpropertyInterpolate7( 69700 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix'); 69701 * ``` 69702 * 69703 * If the property name also exists as an input property on one of the element's directives, 69704 * the component property will be set instead of the element property. This check must 69705 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled. 69706 * 69707 * @param propName The name of the property to update 69708 * @param prefix Static value used for concatenation only. 69709 * @param v0 Value checked for change. 69710 * @param i0 Static value used for concatenation only. 69711 * @param v1 Value checked for change.
69712 * @param i1 Static value used for concatenation only. 69713 * @param v2 Value checked for change. 69714 * @param i2 Static value used for concatenation only. 69715 * @param v3 Value checked for change. 69716 * @param i3 Static value used for concatenation only. 69717 * @param v4 Value checked for change. 69718 * @param i4 Static value used for concatenation only. 69719 * @param v5 Value checked for change. 69720 * @param i5 Static value used for concatenation only. 69721 * @param v6 Value checked for change. 69722 * @param suffix Static value used for concatenation only. 69723 * @param sanitizer An optional sanitizer function 69724 * @returns itself, so that it may be chained. 69725 * @codeGenApi 69726 */ 69727 69728 69729function ɵɵpropertyInterpolate7(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix, sanitizer) { 69730 const lView = getLView(); 69731 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix); 69732 69733 if (interpolatedValue !== NO_CHANGE) { 69734 const tView = getTView(); 69735 const tNode = getSelectedTNode(); 69736 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false); 69737 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 7, prefix, i0, i1, i2, i3, i4, i5, suffix); 69738 } 69739 69740 return ɵɵpropertyInterpolate7; 69741} 69742/** 69743 * 69744 * Update an interpolated property on an element with 8 bound values surrounded by text. 69745 * 69746 * Used when the value passed to a property has 8 interpolated values in it: 69747 * 69748 * ```html 69749 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div> 69750 * ``` 69751 * 69752 * Its compiled representation is:: 69753 * 69754 * ```ts 69755 * ɵɵpropertyInterpolate8( 69756 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix'); 69757 * ``` 69758 * 69759 * If the property name also exists as an input property on one of the element's directives, 69760 * the component property will be set instead of the element property. This check must 69761 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled. 69762 * 69763 * @param propName The name of the property to update 69764 * @param prefix Static value used for concatenation only. 69765 * @param v0 Value checked for change. 69766 * @param i0 Static value used for concatenation only. 69767 * @param v1 Value checked for change. 69768 * @param i1 Static value used for concatenation only. 69769 * @param v2 Value checked for change. 69770 * @param i2 Static value used for concatenation only. 69771 * @param v3 Value checked for change. 69772 * @param i3 Static value used for concatenation only. 69773 * @param v4 Value checked for change. 69774 * @param i4 Static value used for concatenation only. 69775 * @param v5 Value checked for change. 69776 * @param i5 Static value used for concatenation only. 69777 * @param v6 Value checked for change. 69778 * @param i6 Static value used for concatenation only. 69779 * @param v7 Value checked for change. 69780 * @param suffix Static value used for concatenation only. 69781 * @param sanitizer An optional sanitizer function 69782 * @returns itself, so that it may be chained. 69783 * @codeGenApi 69784 */ 69785 69786 69787function ɵɵpropertyInterpolate8(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix, sanitizer) { 69788 const lView = getLView(); 69789 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix); 69790 69791 if (interpolatedValue !== NO_CHANGE) { 69792 const tView = getTView(); 69793 const tNode = getSelectedTNode(); 69794 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false); 69795 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 8, prefix, i0, i1, i2, i3, i4, i5, i6, suffix); 69796 } 69797 69798 return ɵɵpropertyInterpolate8; 69799} 69800/** 69801 * Update an interpolated property on an element with 9 or more bound values surrounded by text. 69802 * 69803 * Used when the number of interpolated values exceeds 8. 69804 * 69805 * ```html 69806 * <div 69807 * title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"></div> 69808 * ``` 69809 * 69810 * Its compiled representation is:: 69811 * 69812 * ```ts 69813 * ɵɵpropertyInterpolateV( 69814 * 'title', ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9, 69815 * 'suffix']); 69816 * ``` 69817 * 69818 * If the property name also exists as an input property on one of the element's directives, 69819 * the component property will be set instead of the element property. This check must 69820 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled. 69821 * 69822 * @param propName The name of the property to update. 69823 * @param values The collection of values and the strings in between those values, beginning with a 69824 * string prefix and ending with a string suffix. 69825 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`) 69826 * @param sanitizer An optional sanitizer function 69827 * @returns itself, so that it may be chained. 69828 * @codeGenApi 69829 */ 69830 69831 69832function ɵɵpropertyInterpolateV(propName, values, sanitizer) { 69833 const lView = getLView(); 69834 const interpolatedValue = interpolationV(lView, values); 69835 69836 if (interpolatedValue !== NO_CHANGE) { 69837 const tView = getTView(); 69838 const tNode = getSelectedTNode(); 69839 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false); 69840 69841 if (ngDevMode) { 69842 const interpolationInBetween = [values[0]]; // prefix 69843 69844 for (let i = 2; i < values.length; i += 2) { 69845 interpolationInBetween.push(values[i]); 69846 } 69847 69848 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - interpolationInBetween.length + 1, ...interpolationInBetween); 69849 } 69850 } 69851 69852 return ɵɵpropertyInterpolateV; 69853} 69854/** 69855 * @license 69856 * Copyright Google LLC All Rights Reserved. 69857 * 69858 * Use of this source code is governed by an MIT-style license that can be 69859 * found in the LICENSE file at https://angular.io/license 69860 */ 69861 69862/** 69863 * NOTE: The word `styling` is used interchangeably as style or class styling. 69864 * 69865 * This file contains code to link styling instructions together so that they can be replayed in 69866 * priority order. The file exists because Ivy styling instruction execution order does not match 69867 * that of the priority order. The purpose of this code is to create a linked list so that the 69868 * instructions can be traversed in priority order when computing the styles. 69869 * 69870 * Assume we are dealing with the following code: 69871 * ``` 69872 * @Component({ 69873 * template: ` 69874 * <my-cmp [style]=" {color: '#001'} " 69875 * [style.color]=" #002 " 69876 * dir-style-color-1 69877 * dir-style-color-2> ` 69878 * })
69879 * class ExampleComponent { 69880 * static ngComp = ... { 69881 * ... 69882 * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap` 69883 * ɵɵstyleMap({color: '#001'}); 69884 * ɵɵstyleProp('color', '#002'); 69885 * ... 69886 * } 69887 * } 69888 * 69889 * @Directive({ 69890 * selector: `[dir-style-color-1]', 69891 * }) 69892 * class Style1Directive { 69893 * @HostBinding('style') style = {color: '#005'}; 69894 * @HostBinding('style.color') color = '#006'; 69895 * 69896 * static ngDir = ... { 69897 * ... 69898 * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap` 69899 * ɵɵstyleMap({color: '#005'}); 69900 * ɵɵstyleProp('color', '#006'); 69901 * ... 69902 * } 69903 * } 69904 * 69905 * @Directive({ 69906 * selector: `[dir-style-color-2]', 69907 * }) 69908 * class Style2Directive { 69909 * @HostBinding('style') style = {color: '#007'}; 69910 * @HostBinding('style.color') color = '#008'; 69911 * 69912 * static ngDir = ... { 69913 * ... 69914 * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap` 69915 * ɵɵstyleMap({color: '#007'}); 69916 * ɵɵstyleProp('color', '#008'); 69917 * ... 69918 * } 69919 * } 69920 * 69921 * @Directive({ 69922 * selector: `my-cmp', 69923 * }) 69924 * class MyComponent { 69925 * @HostBinding('style') style = {color: '#003'}; 69926 * @HostBinding('style.color') color = '#004'; 69927 * 69928 * static ngComp = ... { 69929 * ... 69930 * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap` 69931 * ɵɵstyleMap({color: '#003'}); 69932 * ɵɵstyleProp('color', '#004'); 69933 * ... 69934 * } 69935 * } 69936 * ``` 69937 * 69938 * The Order of instruction execution is: 69939 * 69940 * NOTE: the comment binding location is for illustrative purposes only. 69941 * 69942 * ``` 69943 * // Template: (ExampleComponent) 69944 * ɵɵstyleMap({color: '#001'}); // Binding index: 10 69945 * ɵɵstyleProp('color', '#002'); // Binding index: 12 69946 * // MyComponent 69947 * ɵɵstyleMap({color: '#003'}); // Binding index: 20 69948 * ɵɵstyleProp('color', '#004'); // Binding index: 22 69949 * // Style1Directive 69950 * ɵɵstyleMap({color: '#005'}); // Binding index: 24 69951 * ɵɵstyleProp('color', '#006'); // Binding index: 26 69952 * // Style2Directive 69953 * ɵɵstyleMap({color: '#007'}); // Binding index: 28
69954 * ɵɵstyleProp('color', '#008'); // Binding index: 30 69955 * ``` 69956 * 69957 * The correct priority order of concatenation is: 69958 * 69959 * ``` 69960 * // MyComponent 69961 * ɵɵstyleMap({color: '#003'}); // Binding index: 20 69962 * ɵɵstyleProp('color', '#004'); // Binding index: 22 69963 * // Style1Directive 69964 * ɵɵstyleMap({color: '#005'}); // Binding index: 24 69965 * ɵɵstyleProp('color', '#006'); // Binding index: 26 69966 * // Style2Directive 69967 * ɵɵstyleMap({color: '#007'}); // Binding index: 28 69968 * ɵɵstyleProp('color', '#008'); // Binding index: 30 69969 * // Template: (ExampleComponent) 69970 * ɵɵstyleMap({color: '#001'}); // Binding index: 10 69971 * ɵɵstyleProp('color', '#002'); // Binding index: 12 69972 * ``` 69973 * 69974 * What color should be rendered? 69975 * 69976 * Once the items are correctly sorted in the list, the answer is simply the last item in the 69977 * concatenation list which is `#002`. 69978 * 69979 * To do so we keep a linked list of all of the bindings which pertain to this element. 69980 * Notice that the bindings are inserted in the order of execution, but the `TView.data` allows 69981 * us to traverse them in the order of priority. 69982 * 69983 * |Idx|`TView.data`|`LView` | Notes 69984 * |---|------------|-----------------|-------------- 69985 * |...| | | 69986 * |10 |`null` |`{color: '#001'}`| `ɵɵstyleMap('color', {color: '#001'})` 69987 * |11 |`30 | 12` | ... | 69988 * |12 |`color` |`'#002'` | `ɵɵstyleProp('color', '#002')` 69989 * |13 |`10 | 0` | ... | 69990 * |...| | | 69991 * |20 |`null` |`{color: '#003'}`| `ɵɵstyleMap('color', {color: '#003'})` 69992 * |21 |`0 | 22` | ... | 69993 * |22 |`color` |`'#004'` | `ɵɵstyleProp('color', '#004')` 69994 * |23 |`20 | 24` | ... | 69995 * |24 |`null` |`{color: '#005'}`| `ɵɵstyleMap('color', {color: '#005'})` 69996 * |25 |`22 | 26` | ... | 69997 * |26 |`color` |`'#006'` | `ɵɵstyleProp('color', '#006')` 69998 * |27 |`24 | 28` | ... | 69999 * |28 |`null` |`{color: '#007'}`| `ɵɵstyleMap('color', {color: '#007'})` 70000 * |29 |`26 | 30` | ... | 70001 * |30 |`color` |`'#008'` | `ɵɵstyleProp('color', '#008')` 70002 * |31 |`28 | 10` | ... | 70003 * 70004 * The above data structure allows us to re-concatenate the styling no matter which data binding 70005 * changes. 70006 * 70007 * NOTE: in addition to keeping track of next/previous index the `TView.data` also stores prev/next 70008 * duplicate bit. The duplicate bit if true says there either is a binding with the same name or 70009 * there is a map (which may contain the name). This information is useful in knowing if other 70010 * styles with higher priority need to be searched for overwrites. 70011 * 70012 * NOTE: See `should support example in 'tnode_linked_list.ts' documentation` in 70013 * `tnode_linked_list_spec.ts` for working example. 70014 */ 70015 70016 70017let __unused_const_as_closure_does_not_like_standalone_comment_blocks__; 70018/** 70019 * Insert new `tStyleValue` at `TData` and link existing style bindings such that we maintain linked 70020 * list of styles and compute the duplicate flag. 70021 * 70022 * Note: this function is executed during `firstUpdatePass` only to populate the `TView.data`. 70023 * 70024 * The function works by keeping track of `tStylingRange` which contains two pointers pointing to 70025 * the head/tail of the template portion of the styles. 70026 * - if `isHost === false` (we are template) then insertion is at tail of `TStylingRange` 70027 * - if `isHost === true` (we are host binding) then insertion is at head of `TStylingRange` 70028 * 70029 * @param tData The `TData` to insert into. 70030 * @param tNode `TNode` associated with the styling element. 70031 * @param tStylingKey See `TStylingKey`. 70032 * @param index location of where `tStyleValue` should be stored (and linked into list.) 70033 * @param isHostBinding `true` if the insertion is for a `hostBinding`. (insertion is in front of 70034 * template.) 70035 * @param isClassBinding True if the associated `tStylingKey` as a `class` styling. 70036 * `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.) 70037 */ 70038 70039 70040function insertTStylingBinding(tData, tNode, tStylingKeyWithStatic, index, isHostBinding, isClassBinding) { 70041 ngDevMode && assertFirstUpdatePass(getTView()); 70042 let tBindings = isClassBinding ? tNode.classBindings : tNode.styleBindings; 70043 let tmplHead = getTStylingRangePrev(tBindings); 70044 let tmplTail = getTStylingRangeNext(tBindings); 70045 tData[index] = tStylingKeyWithStatic; 70046 let isKeyDuplicateOfStatic = false;
vendor: 4,725 bytes, lines 70047-70155
70047 let tStylingKey; 70048 70049 if (Array.isArray(tStylingKeyWithStatic)) { 70050 // We are case when the `TStylingKey` contains static fields as well. 70051 const staticKeyValueArray = tStylingKeyWithStatic; 70052 tStylingKey = staticKeyValueArray[1]; // unwrap. 70053 // We need to check if our key is present in the static so that we can mark it as duplicate. 70054 70055 if (tStylingKey === null || keyValueArrayIndexOf(staticKeyValueArray, tStylingKey) > 0) { 70056 // tStylingKey is present in the statics, need to mark it as duplicate. 70057 isKeyDuplicateOfStatic = true; 70058 } 70059 } else { 70060 tStylingKey = tStylingKeyWithStatic; 70061 } 70062 70063 if (isHostBinding) { 70064 // We are inserting host bindings 70065 // If we don't have template bindings then `tail` is 0. 70066 const hasTemplateBindings = tmplTail !== 0; // This is important to know because that means that the `head` can't point to the first 70067 // template bindings (there are none.) Instead the head points to the tail of the template. 70068 70069 if (hasTemplateBindings) { 70070 // template head's "prev" will point to last host binding or to 0 if no host bindings yet 70071 const previousNode = getTStylingRangePrev(tData[tmplHead + 1]); 70072 tData[index + 1] = toTStylingRange(previousNode, tmplHead); // if a host binding has already been registered, we need to update the next of that host 70073 // binding to point to this one 70074 70075 if (previousNode !== 0) { 70076 // We need to update the template-tail value to point to us. 70077 tData[previousNode + 1] = setTStylingRangeNext(tData[previousNode + 1], index); 70078 } // The "previous" of the template binding head should point to this host binding 70079 70080 70081 tData[tmplHead + 1] = setTStylingRangePrev(tData[tmplHead + 1], index); 70082 } else { 70083 tData[index + 1] = toTStylingRange(tmplHead, 0); // if a host binding has already been registered, we need to update the next of that host 70084 // binding to point to this one 70085 70086 if (tmplHead !== 0) { 70087 // We need to update the template-tail value to point to us. 70088 tData[tmplHead + 1] = setTStylingRangeNext(tData[tmplHead + 1], index); 70089 } // if we don't have template, the head points to template-tail, and needs to be advanced. 70090 70091 70092 tmplHead = index; 70093 } 70094 } else { 70095 // We are inserting in template section. 70096 // We need to set this binding's "previous" to the current template tail 70097 tData[index + 1] = toTStylingRange(tmplTail, 0); 70098 ngDevMode && assertEqual(tmplHead !== 0 && tmplTail === 0, false, 'Adding template bindings after hostBindings is not allowed.'); 70099 70100 if (tmplHead === 0) { 70101 tmplHead = index; 70102 } else { 70103 // We need to update the previous value "next" to point to this binding 70104 tData[tmplTail + 1] = setTStylingRangeNext(tData[tmplTail + 1], index); 70105 } 70106 70107 tmplTail = index; 70108 } // Now we need to update / compute the duplicates. 70109 // Starting with our location search towards head (least priority) 70110 70111 70112 if (isKeyDuplicateOfStatic) { 70113 tData[index + 1] = setTStylingRangePrevDuplicate(tData[index + 1]); 70114 } 70115 70116 markDuplicates(tData, tStylingKey, index, true, isClassBinding); 70117 markDuplicates(tData, tStylingKey, index, false, isClassBinding); 70118 markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding); 70119 tBindings = toTStylingRange(tmplHead, tmplTail); 70120 70121 if (isClassBinding) { 70122 tNode.classBindings = tBindings; 70123 } else { 70124 tNode.styleBindings = tBindings; 70125 } 70126} 70127/** 70128 * Look into the residual styling to see if the current `tStylingKey` is duplicate of residual. 70129 * 70130 * @param tNode `TNode` where the residual is stored. 70131 * @param tStylingKey `TStylingKey` to store. 70132 * @param tData `TData` associated with the current `LView`. 70133 * @param index location of where `tStyleValue` should be stored (and linked into list.) 70134 * @param isClassBinding True if the associated `tStylingKey` as a `class` styling. 70135 * `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.) 70136 */ 70137 70138 70139function markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding) { 70140 const residual = isClassBinding ? tNode.residualClasses : tNode.residualStyles; 70141 70142 if (residual != null 70143 /* or undefined */ 70144 && typeof tStylingKey == 'string' && keyValueArrayIndexOf(residual, tStylingKey) >= 0) { 70145 // We have duplicate in the residual so mark ourselves as duplicate. 70146 tData[index + 1] = setTStylingRangeNextDuplicate(tData[index + 1]); 70147 } 70148} 70149/** 70150 * Marks `TStyleValue`s as duplicates if another style binding in the list has the same 70151 * `TStyleValue`. 70152 * 70153 * NOTE: this function is intended to be called twice once with `isPrevDir` set to `true` and once 70154 * with it set to `false` to search both the previous as well as next items in the list. 70155 *
70156 * No duplicate case 70157 * ``` 70158 * [style.color] 70159 * [style.width.px] <<- index 70160 * [style.height.px] 70161 * ``` 70162 * 70163 * In the above case adding `[style.width.px]` to the existing `[style.color]` produces no 70164 * duplicates because `width` is not found in any other part of the linked list. 70165 * 70166 * Duplicate case 70167 * ``` 70168 * [style.color] 70169 * [style.width.em] 70170 * [style.width.px] <<- index 70171 * ``` 70172 * In the above case adding `[style.width.px]` will produce a duplicate with `[style.width.em]` 70173 * because `width` is found in the chain. 70174 * 70175 * Map case 1 70176 * ``` 70177 * [style.width.px] 70178 * [style.color] 70179 * [style] <<- index 70180 * ``` 70181 * In the above case adding `[style]` will produce a duplicate with any other bindings because 70182 * `[style]` is a Map and as such is fully dynamic and could produce `color` or `width`. 70183 * 70184 * Map case 2 70185 * ``` 70186 * [style] 70187 * [style.width.px] 70188 * [style.color] <<- index 70189 * ``` 70190 * In the above case adding `[style.color]` will produce a duplicate because there is already a 70191 * `[style]` binding which is a Map and as such is fully dynamic and could produce `color` or 70192 * `width`. 70193 * 70194 * NOTE: Once `[style]` (Map) is added into the system all things are mapped as duplicates. 70195 * NOTE: We use `style` as example, but same logic is applied to `class`es as well. 70196 * 70197 * @param tData `TData` where the linked list is stored. 70198 * @param tStylingKey `TStylingKeyPrimitive` which contains the value to compare to other keys in 70199 * the linked list. 70200 * @param index Starting location in the linked list to search from 70201 * @param isPrevDir Direction. 70202 * - `true` for previous (lower priority); 70203 * - `false` for next (higher priority). 70204 */ 70205 70206 70207function markDuplicates(tData, tStylingKey, index, isPrevDir, isClassBinding) { 70208 const tStylingAtIndex = tData[index + 1]; 70209 const isMap = tStylingKey === null; 70210 let cursor = isPrevDir ? getTStylingRangePrev(tStylingAtIndex) : getTStylingRangeNext(tStylingAtIndex); 70211 let foundDuplicate = false; // We keep iterating as long as we have a cursor 70212 // AND either: 70213 // - we found what we are looking for, OR 70214 // - we are a map in which case we have to continue searching even after we find what we were 70215 // looking for since we are a wild card and everything needs to be flipped to duplicate. 70216 70217 while (cursor !== 0 && (foundDuplicate === false || isMap)) { 70218 ngDevMode && assertIndexInRange(tData, cursor); 70219 const tStylingValueAtCursor = tData[cursor]; 70220 const tStyleRangeAtCursor = tData[cursor + 1]; 70221 70222 if (isStylingMatch(tStylingValueAtCursor, tStylingKey)) { 70223 foundDuplicate = true; 70224 tData[cursor + 1] = isPrevDir ? setTStylingRangeNextDuplicate(tStyleRangeAtCursor) : setTStylingRangePrevDuplicate(tStyleRangeAtCursor); 70225 } 70226 70227 cursor = isPrevDir ? getTStylingRangePrev(tStyleRangeAtCursor) : getTStylingRangeNext(tStyleRangeAtCursor); 70228 } 70229 70230 if (foundDuplicate) { 70231 // if we found a duplicate, than mark ourselves. 70232 tData[index + 1] = isPrevDir ? setTStylingRangePrevDuplicate(tStylingAtIndex) : setTStylingRangeNextDuplicate(tStylingAtIndex); 70233 } 70234} 70235/** 70236 * Determines if two `TStylingKey`s are a match. 70237 * 70238 * When computing whether a binding contains a duplicate, we need to compare if the instruction 70239 * `TStylingKey` has a match. 70240 * 70241 * Here are examples of `TStylingKey`s which match given `tStylingKeyCursor` is: 70242 * - `color` 70243 * - `color` // Match another color 70244 * - `null` // That means that `tStylingKey` is a `classMap`/`styleMap` instruction 70245 * - `['', 'color', 'other', true]` // wrapped `color` so match 70246 * - `['', null, 'other', true]` // wrapped `null` so match 70247 * - `['', 'width', 'color', 'value']` // wrapped static value contains a match on `'color'` 70248 * - `null` // `tStylingKeyCursor` always match as it is `classMap`/`styleMap` instruction 70249 * 70250 * @param tStylingKeyCursor 70251 * @param tStylingKey 70252 */ 70253 70254 70255function isStylingMatch(tStylingKeyCursor, tStylingKey) { 70256 ngDevMode && assertNotEqual(Array.isArray(tStylingKey), true, 'Expected that \'tStylingKey\' has been unwrapped'); 70257 70258 if (tStylingKeyCursor === null || // If the cursor is `null` it means that we have map at that 70259 // location so we must assume that we have a match. 70260 tStylingKey == null || // If `tStylingKey` is `null` then it is a map therefor assume that it 70261 // contains a match. 70262 (Array.isArray(tStylingKeyCursor) ? tStylingKeyCursor[1] : tStylingKeyCursor) === tStylingKey // If the keys match explicitly than we are a match. 70263 ) { 70264 return true; 70265 } else if (Array.isArray(tStylingKeyCursor) && typeof tStylingKey === 'string') { 70266 // if we did not find a match, but `tStylingKeyCursor` is `KeyValueArray` that means cursor has 70267 // statics and we need to check those as well. 70268 return keyValueArrayIndexOf(tStylingKeyCursor, tStylingKey) >= 0; // see if we are matching the key 70269 } 70270 70271 return false;
vendor: 27,108 bytes, lines 70272-71038
70272} 70273/** 70274 * @license 70275 * Copyright Google LLC All Rights Reserved. 70276 * 70277 * Use of this source code is governed by an MIT-style license that can be 70278 * found in the LICENSE file at https://angular.io/license 70279 */ 70280// Global state of the parser. (This makes parser non-reentrant, but that is not an issue) 70281 70282 70283const parserState = { 70284 textEnd: 0, 70285 key: 0, 70286 keyEnd: 0, 70287 value: 0, 70288 valueEnd: 0 70289}; 70290/** 70291 * Retrieves the last parsed `key` of style. 70292 * @param text the text to substring the key from. 70293 */ 70294 70295function getLastParsedKey(text) { 70296 return text.substring(parserState.key, parserState.keyEnd); 70297} 70298/** 70299 * Retrieves the last parsed `value` of style. 70300 * @param text the text to substring the key from. 70301 */ 70302 70303 70304function getLastParsedValue(text) { 70305 return text.substring(parserState.value, parserState.valueEnd); 70306} 70307/** 70308 * Initializes `className` string for parsing and parses the first token. 70309 * 70310 * This function is intended to be used in this format: 70311 * ``` 70312 * for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) { 70313 * const key = getLastParsedKey(); 70314 * ... 70315 * } 70316 * ``` 70317 * @param text `className` to parse 70318 * @returns index where the next invocation of `parseClassNameNext` should resume. 70319 */ 70320 70321 70322function parseClassName(text) { 70323 resetParserState(text); 70324 return parseClassNameNext(text, consumeWhitespace(text, 0, parserState.textEnd)); 70325} 70326/** 70327 * Parses next `className` token. 70328 * 70329 * This function is intended to be used in this format: 70330 * ``` 70331 * for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) { 70332 * const key = getLastParsedKey(); 70333 * ... 70334 * } 70335 * ``` 70336 * 70337 * @param text `className` to parse 70338 * @param index where the parsing should resume. 70339 * @returns index where the next invocation of `parseClassNameNext` should resume. 70340 */ 70341 70342 70343function parseClassNameNext(text, index) { 70344 const end = parserState.textEnd; 70345 70346 if (end === index) { 70347 return -1; 70348 } 70349 70350 index = parserState.keyEnd = consumeClassToken(text, parserState.key = index, end); 70351 return consumeWhitespace(text, index, end); 70352} 70353/** 70354 * Initializes `cssText` string for parsing and parses the first key/values. 70355 * 70356 * This function is intended to be used in this format: 70357 * ``` 70358 * for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i))) { 70359 * const key = getLastParsedKey(); 70360 * const value = getLastParsedValue(); 70361 * ... 70362 * } 70363 * ``` 70364 * @param text `cssText` to parse 70365 * @returns index where the next invocation of `parseStyleNext` should resume. 70366 */ 70367 70368 70369function parseStyle(text) { 70370 resetParserState(text); 70371 return parseStyleNext(text, consumeWhitespace(text, 0, parserState.textEnd)); 70372} 70373/** 70374 * Parses the next `cssText` key/values. 70375 * 70376 * This function is intended to be used in this format: 70377 * ``` 70378 * for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i))) { 70379 * const key = getLastParsedKey(); 70380 * const value = getLastParsedValue(); 70381 * ... 70382 * } 70383 * 70384 * @param text `cssText` to parse 70385 * @param index where the parsing should resume. 70386 * @returns index where the next invocation of `parseStyleNext` should resume. 70387 */ 70388 70389 70390function parseStyleNext(text, startIndex) { 70391 const end = parserState.textEnd; 70392 let index = parserState.key = consumeWhitespace(text, startIndex, end); 70393 70394 if (end === index) { 70395 // we reached an end so just quit 70396 return -1; 70397 } 70398 70399 index = parserState.keyEnd = consumeStyleKey(text, index, end); 70400 index = consumeSeparator(text, index, end, 58 70401 /* CharCode.COLON */ 70402 ); 70403 index = parserState.value = consumeWhitespace(text, index, end); 70404 index = parserState.valueEnd = consumeStyleValue(text, index, end); 70405 return consumeSeparator(text, index, end, 59 70406 /* CharCode.SEMI_COLON */ 70407 ); 70408} 70409/** 70410 * Reset the global state of the styling parser. 70411 * @param text The styling text to parse. 70412 */ 70413 70414 70415function resetParserState(text) { 70416 parserState.key = 0; 70417 parserState.keyEnd = 0; 70418 parserState.value = 0; 70419 parserState.valueEnd = 0; 70420 parserState.textEnd = text.length; 70421} 70422/** 70423 * Returns index of next non-whitespace character. 70424 * 70425 * @param text Text to scan 70426 * @param startIndex Starting index of character where the scan should start. 70427 * @param endIndex Ending index of character where the scan should end. 70428 * @returns Index of next non-whitespace character (May be the same as `start` if no whitespace at 70429 * that location.) 70430 */ 70431 70432 70433function consumeWhitespace(text, startIndex, endIndex) { 70434 while (startIndex < endIndex && text.charCodeAt(startIndex) <= 32 70435 /* CharCode.SPACE */ 70436 ) { 70437 startIndex++; 70438 } 70439 70440 return startIndex; 70441} 70442/** 70443 * Returns index of last char in class token. 70444 * 70445 * @param text Text to scan 70446 * @param startIndex Starting index of character where the scan should start. 70447 * @param endIndex Ending index of character where the scan should end. 70448 * @returns Index after last char in class token. 70449 */ 70450 70451 70452function consumeClassToken(text, startIndex, endIndex) { 70453 while (startIndex < endIndex && text.charCodeAt(startIndex) > 32 70454 /* CharCode.SPACE */ 70455 ) { 70456 startIndex++; 70457 } 70458 70459 return startIndex; 70460} 70461/** 70462 * Consumes all of the characters belonging to style key and token. 70463 * 70464 * @param text Text to scan 70465 * @param startIndex Starting index of character where the scan should start. 70466 * @param endIndex Ending index of character where the scan should end. 70467 * @returns Index after last style key character. 70468 */ 70469 70470 70471function consumeStyleKey(text, startIndex, endIndex) { 70472 let ch; 70473 70474 while (startIndex < endIndex && ((ch = text.charCodeAt(startIndex)) === 45 70475 /* CharCode.DASH */ 70476 || ch === 95 70477 /* CharCode.UNDERSCORE */ 70478 || (ch & -33 70479 /* CharCode.UPPER_CASE */ 70480 ) >= 65 70481 /* CharCode.A */ 70482 && (ch & -33 70483 /* CharCode.UPPER_CASE */ 70484 ) <= 90 70485 /* CharCode.Z */ 70486 || ch >= 48 70487 /* CharCode.ZERO */ 70488 && ch <= 57 70489 /* CharCode.NINE */ 70490 )) { 70491 startIndex++; 70492 } 70493 70494 return startIndex; 70495} 70496/** 70497 * Consumes all whitespace and the separator `:` after the style key. 70498 * 70499 * @param text Text to scan 70500 * @param startIndex Starting index of character where the scan should start. 70501 * @param endIndex Ending index of character where the scan should end. 70502 * @returns Index after separator and surrounding whitespace. 70503 */ 70504 70505 70506function consumeSeparator(text, startIndex, endIndex, separator) { 70507 startIndex = consumeWhitespace(text, startIndex, endIndex); 70508 70509 if (startIndex < endIndex) { 70510 if (ngDevMode && text.charCodeAt(startIndex) !== separator) { 70511 malformedStyleError(text, String.fromCharCode(separator), startIndex); 70512 } 70513 70514 startIndex++; 70515 } 70516 70517 return startIndex; 70518} 70519/** 70520 * Consumes style value honoring `url()` and `""` text. 70521 * 70522 * @param text Text to scan 70523 * @param startIndex Starting index of character where the scan should start. 70524 * @param endIndex Ending index of character where the scan should end. 70525 * @returns Index after last style value character. 70526 */ 70527 70528 70529function consumeStyleValue(text, startIndex, endIndex) { 70530 let ch1 = -1; // 1st previous character 70531 70532 let ch2 = -1; // 2nd previous character 70533 70534 let ch3 = -1; // 3rd previous character 70535 70536 let i = startIndex; 70537 let lastChIndex = i; 70538 70539 while (i < endIndex) { 70540 const ch = text.charCodeAt(i++); 70541 70542 if (ch === 59 70543 /* CharCode.SEMI_COLON */ 70544 ) { 70545 return lastChIndex; 70546 } else if (ch === 34 70547 /* CharCode.DOUBLE_QUOTE */ 70548 || ch === 39 70549 /* CharCode.SINGLE_QUOTE */ 70550 ) { 70551 lastChIndex = i = consumeQuotedText(text, ch, i, endIndex); 70552 } else if (startIndex === i - 4 && // We have seen only 4 characters so far "URL(" (Ignore "foo_URL()") 70553 ch3 === 85 70554 /* CharCode.U */ 70555 && ch2 === 82 70556 /* CharCode.R */ 70557 && ch1 === 76 70558 /* CharCode.L */ 70559 && ch === 40 70560 /* CharCode.OPEN_PAREN */ 70561 ) { 70562 lastChIndex = i = consumeQuotedText(text, 41 70563 /* CharCode.CLOSE_PAREN */ 70564 , i, endIndex); 70565 } else if (ch > 32 70566 /* CharCode.SPACE */ 70567 ) { 70568 // if we have a non-whitespace character then capture its location 70569 lastChIndex = i; 70570 } 70571 70572 ch3 = ch2; 70573 ch2 = ch1; 70574 ch1 = ch & -33 70575 /* CharCode.UPPER_CASE */ 70576 ; 70577 } 70578 70579 return lastChIndex; 70580} 70581/** 70582 * Consumes all of the quoted characters. 70583 * 70584 * @param text Text to scan 70585 * @param quoteCharCode CharCode of either `"` or `'` quote or `)` for `url(...)`. 70586 * @param startIndex Starting index of character where the scan should start. 70587 * @param endIndex Ending index of character where the scan should end. 70588 * @returns Index after quoted characters. 70589 */ 70590 70591 70592function consumeQuotedText(text, quoteCharCode, startIndex, endIndex) { 70593 let ch1 = -1; // 1st previous character 70594 70595 let index = startIndex; 70596 70597 while (index < endIndex) { 70598 const ch = text.charCodeAt(index++); 70599 70600 if (ch == quoteCharCode && ch1 !== 92 70601 /* CharCode.BACK_SLASH */ 70602 ) { 70603 return index; 70604 } 70605 70606 if (ch == 92 70607 /* CharCode.BACK_SLASH */ 70608 && ch1 === 92 70609 /* CharCode.BACK_SLASH */ 70610 ) { 70611 // two back slashes cancel each other out. For example `"\\"` should properly end the 70612 // quotation. (It should not assume that the last `"` is escaped.) 70613 ch1 = 0; 70614 } else { 70615 ch1 = ch; 70616 } 70617 } 70618 70619 throw ngDevMode ? malformedStyleError(text, String.fromCharCode(quoteCharCode), endIndex) : new Error(); 70620} 70621 70622function malformedStyleError(text, expecting, index) { 70623 ngDevMode && assertEqual(typeof text === 'string', true, 'String expected here'); 70624 throw throwError(`Malformed style at location ${index} in string '` + text.substring(0, index) + '[>>' + text.substring(index, index + 1) + '<<]' + text.slice(index + 1) + `'. Expecting '${expecting}'.`); 70625} 70626/** 70627 * @license 70628 * Copyright Google LLC All Rights Reserved. 70629 * 70630 * Use of this source code is governed by an MIT-style license that can be 70631 * found in the LICENSE file at https://angular.io/license 70632 */ 70633 70634/** 70635 * Update a style binding on an element with the provided value. 70636 * 70637 * If the style value is falsy then it will be removed from the element 70638 * (or assigned a different value depending if there are any styles placed 70639 * on the element with `styleMap` or any static styles that are 70640 * present from when the element was created with `styling`). 70641 * 70642 * Note that the styling element is updated as part of `stylingApply`. 70643 * 70644 * @param prop A valid CSS property. 70645 * @param value New value to write (`null` or an empty string to remove). 70646 * @param suffix Optional suffix. Used with scalar values to add unit such as `px`. 70647 * 70648 * Note that this will apply the provided style value to the host element if this function is called 70649 * within a host binding function. 70650 * 70651 * @codeGenApi 70652 */ 70653 70654 70655function ɵɵstyleProp(prop, value, suffix) { 70656 checkStylingProperty(prop, value, suffix, false); 70657 return ɵɵstyleProp; 70658} 70659/** 70660 * Update a class binding on an element with the provided value. 70661 * 70662 * This instruction is meant to handle the `[class.foo]="exp"` case and, 70663 * therefore, the class binding itself must already be allocated using 70664 * `styling` within the creation block. 70665 * 70666 * @param prop A valid CSS class (only one). 70667 * @param value A true/false value which will turn the class on or off. 70668 * 70669 * Note that this will apply the provided class value to the host element if this function 70670 * is called within a host binding function. 70671 * 70672 * @codeGenApi 70673 */ 70674 70675 70676function ɵɵclassProp(className, value) { 70677 checkStylingProperty(className, value, null, true); 70678 return ɵɵclassProp; 70679} 70680/** 70681 * Update style bindings using an object literal on an element. 70682 * 70683 * This instruction is meant to apply styling via the `[style]="exp"` template bindings. 70684 * When styles are applied to the element they will then be updated with respect to 70685 * any styles/classes set via `styleProp`. If any styles are set to falsy 70686 * then they will be removed from the element. 70687 * 70688 * Note that the styling instruction will not be applied until `stylingApply` is called. 70689 * 70690 * @param styles A key/value style map of the styles that will be applied to the given element. 70691 * Any missing styles (that have already been applied to the element beforehand) will be 70692 * removed (unset) from the element's styling. 70693 * 70694 * Note that this will apply the provided styleMap value to the host element if this function 70695 * is called within a host binding. 70696 * 70697 * @codeGenApi 70698 */ 70699 70700 70701function ɵɵstyleMap(styles) { 70702 checkStylingMap(styleKeyValueArraySet, styleStringParser, styles, false); 70703} 70704/** 70705 * Parse text as style and add values to KeyValueArray. 70706 * 70707 * This code is pulled out to a separate function so that it can be tree shaken away if it is not 70708 * needed. It is only referenced from `ɵɵstyleMap`. 70709 * 70710 * @param keyValueArray KeyValueArray to add parsed values to. 70711 * @param text text to parse. 70712 */ 70713 70714 70715function styleStringParser(keyValueArray, text) { 70716 for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i)) { 70717 styleKeyValueArraySet(keyValueArray, getLastParsedKey(text), getLastParsedValue(text)); 70718 } 70719} 70720/** 70721 * Update class bindings using an object literal or class-string on an element. 70722 * 70723 * This instruction is meant to apply styling via the `[class]="exp"` template bindings. 70724 * When classes are applied to the element they will then be updated with 70725 * respect to any styles/classes set via `classProp`. If any 70726 * classes are set to falsy then they will be removed from the element. 70727 * 70728 * Note that the styling instruction will not be applied until `stylingApply` is called. 70729 * Note that this will the provided classMap value to the host element if this function is called 70730 * within a host binding. 70731 * 70732 * @param classes A key/value map or string of CSS classes that will be added to the 70733 * given element. Any missing classes (that have already been applied to the element 70734 * beforehand) will be removed (unset) from the element's list of CSS classes. 70735 * 70736 * @codeGenApi 70737 */ 70738 70739 70740function ɵɵclassMap(classes) { 70741 checkStylingMap(keyValueArraySet, classStringParser, classes, true); 70742} 70743/** 70744 * Parse text as class and add values to KeyValueArray. 70745 * 70746 * This code is pulled out to a separate function so that it can be tree shaken away if it is not 70747 * needed. It is only referenced from `ɵɵclassMap`. 70748 * 70749 * @param keyValueArray KeyValueArray to add parsed values to. 70750 * @param text text to parse. 70751 */ 70752 70753 70754function classStringParser(keyValueArray, text) { 70755 for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) { 70756 keyValueArraySet(keyValueArray, getLastParsedKey(text), true); 70757 } 70758} 70759/** 70760 * Common code between `ɵɵclassProp` and `ɵɵstyleProp`. 70761 * 70762 * @param prop property name. 70763 * @param value binding value. 70764 * @param suffix suffix for the property (e.g. `em` or `px`) 70765 * @param isClassBased `true` if `class` change (`false` if `style`) 70766 */ 70767 70768 70769function checkStylingProperty(prop, value, suffix, isClassBased) { 70770 const lView = getLView(); 70771 const tView = getTView(); // Styling instructions use 2 slots per binding. 70772 // 1. one for the value / TStylingKey 70773 // 2. one for the intermittent-value / TStylingRange 70774 70775 const bindingIndex = incrementBindingIndex(2); 70776 70777 if (tView.firstUpdatePass) { 70778 stylingFirstUpdatePass(tView, prop, bindingIndex, isClassBased); 70779 } 70780 70781 if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) { 70782 const tNode = tView.data[getSelectedIndex()]; 70783 updateStyling(tView, tNode, lView, lView[RENDERER], prop, lView[bindingIndex + 1] = normalizeSuffix(value, suffix), isClassBased, bindingIndex); 70784 } 70785} 70786/** 70787 * Common code between `ɵɵclassMap` and `ɵɵstyleMap`. 70788 * 70789 * @param keyValueArraySet (See `keyValueArraySet` in "util/array_utils") Gets passed in as a 70790 * function so that `style` can be processed. This is done for tree shaking purposes. 70791 * @param stringParser Parser used to parse `value` if `string`. (Passed in as `style` and `class` 70792 * have different parsers.) 70793 * @param value bound value from application 70794 * @param isClassBased `true` if `class` change (`false` if `style`) 70795 */ 70796 70797 70798function checkStylingMap(keyValueArraySet, stringParser, value, isClassBased) { 70799 const tView = getTView(); 70800 const bindingIndex = incrementBindingIndex(2); 70801 70802 if (tView.firstUpdatePass) { 70803 stylingFirstUpdatePass(tView, null, bindingIndex, isClassBased); 70804 } 70805 70806 const lView = getLView(); 70807 70808 if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) { 70809 // `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the 70810 // if so as not to read unnecessarily. 70811 const tNode = tView.data[getSelectedIndex()]; 70812 70813 if (hasStylingInputShadow(tNode, isClassBased) && !isInHostBindings(tView, bindingIndex)) { 70814 if (ngDevMode) { 70815 // verify that if we are shadowing then `TData` is appropriately marked so that we skip 70816 // processing this binding in styling resolution. 70817 const tStylingKey = tView.data[bindingIndex]; 70818 assertEqual(Array.isArray(tStylingKey) ? tStylingKey[1] : tStylingKey, false, 'Styling linked list shadow input should be marked as \'false\''); 70819 } // VE does not concatenate the static portion like we are doing here. 70820 // Instead VE just ignores the static completely if dynamic binding is present. 70821 // Because of locality we have already set the static portion because we don't know if there 70822 // is a dynamic portion until later. If we would ignore the static portion it would look like 70823 // the binding has removed it. This would confuse `[ngStyle]`/`[ngClass]` to do the wrong 70824 // thing as it would think that the static portion was removed. For this reason we 70825 // concatenate it so that `[ngStyle]`/`[ngClass]` can continue to work on changed. 70826 70827 70828 let staticPrefix = isClassBased ? tNode.classesWithoutHost : tNode.stylesWithoutHost; 70829 ngDevMode && isClassBased === false && staticPrefix !== null && assertEqual(staticPrefix.endsWith(';'), true, 'Expecting static portion to end with \';\''); 70830 70831 if (staticPrefix !== null) { 70832 // We want to make sure that falsy values of `value` become empty strings. 70833 value = concatStringsWithSpace(staticPrefix, value ? value : ''); 70834 } // Given `<div [style] my-dir>` such that `my-dir` has `@Input('style')`. 70835 // This takes over the `[style]` binding. (Same for `[class]`) 70836 70837 70838 setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased); 70839 } else { 70840 updateStylingMap(tView, tNode, lView, lView[RENDERER], lView[bindingIndex + 1], lView[bindingIndex + 1] = toStylingKeyValueArray(keyValueArraySet, stringParser, value), isClassBased, bindingIndex); 70841 } 70842 } 70843} 70844/** 70845 * Determines when the binding is in `hostBindings` section 70846 * 70847 * @param tView Current `TView` 70848 * @param bindingIndex index of binding which we would like if it is in `hostBindings` 70849 */ 70850 70851 70852function isInHostBindings(tView, bindingIndex) { 70853 // All host bindings are placed after the expando section. 70854 return bindingIndex >= tView.expandoStartIndex; 70855} 70856/** 70857 * Collects the necessary information to insert the binding into a linked list of style bindings 70858 * using `insertTStylingBinding`. 70859 * 70860 * @param tView `TView` where the binding linked list will be stored. 70861 * @param tStylingKey Property/key of the binding. 70862 * @param bindingIndex Index of binding associated with the `prop` 70863 * @param isClassBased `true` if `class` change (`false` if `style`) 70864 */ 70865 70866 70867function stylingFirstUpdatePass(tView, tStylingKey, bindingIndex, isClassBased) { 70868 ngDevMode && assertFirstUpdatePass(tView); 70869 const tData = tView.data; 70870 70871 if (tData[bindingIndex + 1] === null) { 70872 // The above check is necessary because we don't clear first update pass until first successful 70873 // (no exception) template execution. This prevents the styling instruction from double adding 70874 // itself to the list. 70875 // `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the 70876 // if so as not to read unnecessarily. 70877 const tNode = tData[getSelectedIndex()]; 70878 ngDevMode && assertDefined(tNode, 'TNode expected'); 70879 const isHostBindings = isInHostBindings(tView, bindingIndex); 70880 70881 if (hasStylingInputShadow(tNode, isClassBased) && tStylingKey === null && !isHostBindings) { 70882 // `tStylingKey === null` implies that we are either `[style]` or `[class]` binding. 70883 // If there is a directive which uses `@Input('style')` or `@Input('class')` than 70884 // we need to neutralize this binding since that directive is shadowing it. 70885 // We turn this into a noop by setting the key to `false` 70886 tStylingKey = false; 70887 } 70888 70889 tStylingKey = wrapInStaticStylingKey(tData, tNode, tStylingKey, isClassBased); 70890 insertTStylingBinding(tData, tNode, tStylingKey, bindingIndex, isHostBindings, isClassBased); 70891 } 70892} 70893/** 70894 * Adds static styling information to the binding if applicable. 70895 * 70896 * The linked list of styles not only stores the list and keys, but also stores static styling 70897 * information on some of the keys. This function determines if the key should contain the styling 70898 * information and computes it. 70899 * 70900 * See `TStylingStatic` for more details. 70901 * 70902 * @param tData `TData` where the linked list is stored. 70903 * @param tNode `TNode` for which the styling is being computed. 70904 * @param stylingKey `TStylingKeyPrimitive` which may need to be wrapped into `TStylingKey` 70905 * @param isClassBased `true` if `class` (`false` if `style`) 70906 */ 70907 70908 70909function wrapInStaticStylingKey(tData, tNode, stylingKey, isClassBased) { 70910 const hostDirectiveDef = getCurrentDirectiveDef(tData); 70911 let residual = isClassBased ? tNode.residualClasses : tNode.residualStyles; 70912 70913 if (hostDirectiveDef === null) { 70914 // We are in template node. 70915 // If template node already had styling instruction then it has already collected the static 70916 // styling and there is no need to collect them again. We know that we are the first styling 70917 // instruction because the `TNode.*Bindings` points to 0 (nothing has been inserted yet). 70918 const isFirstStylingInstructionInTemplate = (isClassBased ? tNode.classBindings : tNode.styleBindings) === 0; 70919 70920 if (isFirstStylingInstructionInTemplate) { 70921 // It would be nice to be able to get the statics from `mergeAttrs`, however, at this point 70922 // they are already merged and it would not be possible to figure which property belongs where 70923 // in the priority. 70924 stylingKey = collectStylingFromDirectives(null, tData, tNode, stylingKey, isClassBased); 70925 stylingKey = collectStylingFromTAttrs(stylingKey, tNode.attrs, isClassBased); // We know that if we have styling binding in template we can't have residual. 70926 70927 residual = null; 70928 } 70929 } else { 70930 // We are in host binding node and there was no binding instruction in template node. 70931 // This means that we need to compute the residual. 70932 const directiveStylingLast = tNode.directiveStylingLast; 70933 const isFirstStylingInstructionInHostBinding = directiveStylingLast === -1 || tData[directiveStylingLast] !== hostDirectiveDef; 70934 70935 if (isFirstStylingInstructionInHostBinding) { 70936 stylingKey = collectStylingFromDirectives(hostDirectiveDef, tData, tNode, stylingKey, isClassBased); 70937 70938 if (residual === null) { 70939 // - If `null` than either: 70940 // - Template styling instruction already ran and it has consumed the static 70941 // styling into its `TStylingKey` and so there is no need to update residual. Instead 70942 // we need to update the `TStylingKey` associated with the first template node 70943 // instruction. OR 70944 // - Some other styling instruction ran and determined that there are no residuals 70945 let templateStylingKey = getTemplateHeadTStylingKey(tData, tNode, isClassBased); 70946 70947 if (templateStylingKey !== undefined && Array.isArray(templateStylingKey)) { 70948 // Only recompute if `templateStylingKey` had static values. (If no static value found 70949 // then there is nothing to do since this operation can only produce less static keys, not 70950 // more.) 70951 templateStylingKey = collectStylingFromDirectives(null, tData, tNode, templateStylingKey[1] 70952 /* unwrap previous statics */ 70953 , isClassBased); 70954 templateStylingKey = collectStylingFromTAttrs(templateStylingKey, tNode.attrs, isClassBased); 70955 setTemplateHeadTStylingKey(tData, tNode, isClassBased, templateStylingKey); 70956 } 70957 } else { 70958 // We only need to recompute residual if it is not `null`. 70959 // - If existing residual (implies there was no template styling). This means that some of 70960 // the statics may have moved from the residual to the `stylingKey` and so we have to 70961 // recompute. 70962 // - If `undefined` this is the first time we are running. 70963 residual = collectResidual(tData, tNode, isClassBased); 70964 } 70965 } 70966 } 70967 70968 if (residual !== undefined) { 70969 isClassBased ? tNode.residualClasses = residual : tNode.residualStyles = residual; 70970 } 70971 70972 return stylingKey; 70973} 70974/** 70975 * Retrieve the `TStylingKey` for the template styling instruction. 70976 * 70977 * This is needed since `hostBinding` styling instructions are inserted after the template 70978 * instruction. While the template instruction needs to update the residual in `TNode` the 70979 * `hostBinding` instructions need to update the `TStylingKey` of the template instruction because 70980 * the template instruction is downstream from the `hostBindings` instructions. 70981 * 70982 * @param tData `TData` where the linked list is stored. 70983 * @param tNode `TNode` for which the styling is being computed. 70984 * @param isClassBased `true` if `class` (`false` if `style`) 70985 * @return `TStylingKey` if found or `undefined` if not found. 70986 */ 70987 70988 70989function getTemplateHeadTStylingKey(tData, tNode, isClassBased) { 70990 const bindings = isClassBased ? tNode.classBindings : tNode.styleBindings; 70991 70992 if (getTStylingRangeNext(bindings) === 0) { 70993 // There does not seem to be a styling instruction in the `template`. 70994 return undefined; 70995 } 70996 70997 return tData[getTStylingRangePrev(bindings)]; 70998} 70999/** 71000 * Update the `TStylingKey` of the first template instruction in `TNode`. 71001 * 71002 * Logically `hostBindings` styling instructions are of lower priority than that of the template. 71003 * However, they execute after the template styling instructions. This means that they get inserted 71004 * in front of the template styling instructions. 71005 * 71006 * If we have a template styling instruction and a new `hostBindings` styling instruction is 71007 * executed it means that it may need to steal static fields from the template instruction. This 71008 * method allows us to update the first template instruction `TStylingKey` with a new value. 71009 * 71010 * Assume: 71011 * ``` 71012 * <div my-dir style="color: red" [style.color]="tmplExp"></div> 71013 * 71014 * @Directive({ 71015 * host: { 71016 * 'style': 'width: 100px', 71017 * '[style.color]': 'dirExp', 71018 * } 71019 * }) 71020 * class MyDir {} 71021 * ``` 71022 * 71023 * when `[style.color]="tmplExp"` executes it creates this data structure. 71024 * ``` 71025 * ['', 'color', 'color', 'red', 'width', '100px'], 71026 * ``` 71027 * 71028 * The reason for this is that the template instruction does not know if there are styling 71029 * instructions and must assume that there are none and must collect all of the static styling. 71030 * (both 71031 * `color' and 'width`) 71032 * 71033 * When `'[style.color]': 'dirExp',` executes we need to insert a new data into the linked list. 71034 * ``` 71035 * ['', 'color', 'width', '100px'], // newly inserted 71036 * ['', 'color', 'color', 'red', 'width', '100px'], // this is wrong 71037 * ``` 71038 *
71039 * Notice that the template statics is now wrong as it incorrectly contains `width` so we need to 71040 * update it like so: 71041 * ``` 71042 * ['', 'color', 'width', '100px'], 71043 * ['', 'color', 'color', 'red'], // UPDATE 71044 * ``` 71045 * 71046 * @param tData `TData` where the linked list is stored. 71047 * @param tNode `TNode` for which the styling is being computed. 71048 * @param isClassBased `true` if `class` (`false` if `style`) 71049 * @param tStylingKey New `TStylingKey` which is replacing the old one. 71050 */ 71051 71052 71053function setTemplateHeadTStylingKey(tData, tNode, isClassBased, tStylingKey) { 71054 const bindings = isClassBased ? tNode.classBindings : tNode.styleBindings; 71055 ngDevMode && assertNotEqual(getTStylingRangeNext(bindings), 0, 'Expecting to have at least one template styling binding.'); 71056 tData[getTStylingRangePrev(bindings)] = tStylingKey; 71057} 71058/** 71059 * Collect all static values after the current `TNode.directiveStylingLast` index. 71060 * 71061 * Collect the remaining styling information which has not yet been collected by an existing 71062 * styling instruction. 71063 * 71064 * @param tData `TData` where the `DirectiveDefs` are stored. 71065 * @param tNode `TNode` which contains the directive range. 71066 * @param isClassBased `true` if `class` (`false` if `style`) 71067 */ 71068 71069 71070function collectResidual(tData, tNode, isClassBased) { 71071 let residual = undefined; 71072 const directiveEnd = tNode.directiveEnd; 71073 ngDevMode && assertNotEqual(tNode.directiveStylingLast, -1, 'By the time this function gets called at least one hostBindings-node styling instruction must have executed.'); // We add `1 + tNode.directiveStart` because we need to skip the current directive (as we are 71074 // collecting things after the last `hostBindings` directive which had a styling instruction.) 71075 71076 for (let i = 1 + tNode.directiveStylingLast; i < directiveEnd; i++) { 71077 const attrs = tData[i].hostAttrs; 71078 residual = collectStylingFromTAttrs(residual, attrs, isClassBased); 71079 } 71080 71081 return collectStylingFromTAttrs(residual, tNode.attrs, isClassBased); 71082} 71083/** 71084 * Collect the static styling information with lower priority than `hostDirectiveDef`. 71085 * 71086 * (This is opposite of residual styling.) 71087 * 71088 * @param hostDirectiveDef `DirectiveDef` for which we want to collect lower priority static 71089 * styling. (Or `null` if template styling) 71090 * @param tData `TData` where the linked list is stored. 71091 * @param tNode `TNode` for which the styling is being computed. 71092 * @param stylingKey Existing `TStylingKey` to update or wrap. 71093 * @param isClassBased `true` if `class` (`false` if `style`) 71094 */ 71095 71096 71097function collectStylingFromDirectives(hostDirectiveDef, tData, tNode, stylingKey, isClassBased) { 71098 // We need to loop because there can be directives which have `hostAttrs` but don't have 71099 // `hostBindings` so this loop catches up to the current directive.. 71100 let currentDirective = null; 71101 const directiveEnd = tNode.directiveEnd; 71102 let directiveStylingLast = tNode.directiveStylingLast; 71103 71104 if (directiveStylingLast === -1) { 71105 directiveStylingLast = tNode.directiveStart; 71106 } else { 71107 directiveStylingLast++; 71108 } 71109 71110 while (directiveStylingLast < directiveEnd) { 71111 currentDirective = tData[directiveStylingLast]; 71112 ngDevMode && assertDefined(currentDirective, 'expected to be defined'); 71113 stylingKey = collectStylingFromTAttrs(stylingKey, currentDirective.hostAttrs, isClassBased); 71114 if (currentDirective === hostDirectiveDef) break; 71115 directiveStylingLast++; 71116 } 71117 71118 if (hostDirectiveDef !== null) { 71119 // we only advance the styling cursor if we are collecting data from host bindings. 71120 // Template executes before host bindings and so if we would update the index, 71121 // host bindings would not get their statics. 71122 tNode.directiveStylingLast = directiveStylingLast; 71123 } 71124 71125 return stylingKey; 71126} 71127/** 71128 * Convert `TAttrs` into `TStylingStatic`. 71129 * 71130 * @param stylingKey existing `TStylingKey` to update or wrap. 71131 * @param attrs `TAttributes` to process. 71132 * @param isClassBased `true` if `class` (`false` if `style`) 71133 */ 71134 71135 71136function collectStylingFromTAttrs(stylingKey, attrs, isClassBased) { 71137 const desiredMarker = isClassBased ? 1 71138 /* AttributeMarker.Classes */ 71139 : 2 71140 /* AttributeMarker.Styles */ 71141 ; 71142 let currentMarker = -1 71143 /* AttributeMarker.ImplicitAttributes */ 71144 ; 71145 71146 if (attrs !== null) { 71147 for (let i = 0; i < attrs.length; i++) { 71148 const item = attrs[i]; 71149 71150 if (typeof item === 'number') { 71151 currentMarker = item; 71152 } else {
vendor: 17,808 bytes, lines 71153-71648
71153 if (currentMarker === desiredMarker) { 71154 if (!Array.isArray(stylingKey)) { 71155 stylingKey = stylingKey === undefined ? [] : ['', stylingKey]; 71156 } 71157 71158 keyValueArraySet(stylingKey, item, isClassBased ? true : attrs[++i]); 71159 } 71160 } 71161 } 71162 } 71163 71164 return stylingKey === undefined ? null : stylingKey; 71165} 71166/** 71167 * Convert user input to `KeyValueArray`. 71168 * 71169 * This function takes user input which could be `string`, Object literal, or iterable and converts 71170 * it into a consistent representation. The output of this is `KeyValueArray` (which is an array 71171 * where 71172 * even indexes contain keys and odd indexes contain values for those keys). 71173 * 71174 * The advantage of converting to `KeyValueArray` is that we can perform diff in an input 71175 * independent 71176 * way. 71177 * (ie we can compare `foo bar` to `['bar', 'baz'] and determine a set of changes which need to be 71178 * applied) 71179 * 71180 * The fact that `KeyValueArray` is sorted is very important because it allows us to compute the 71181 * difference in linear fashion without the need to allocate any additional data. 71182 * 71183 * For example if we kept this as a `Map` we would have to iterate over previous `Map` to determine 71184 * which values need to be deleted, over the new `Map` to determine additions, and we would have to 71185 * keep additional `Map` to keep track of duplicates or items which have not yet been visited. 71186 * 71187 * @param keyValueArraySet (See `keyValueArraySet` in "util/array_utils") Gets passed in as a 71188 * function so that `style` can be processed. This is done 71189 * for tree shaking purposes. 71190 * @param stringParser The parser is passed in so that it will be tree shakable. See 71191 * `styleStringParser` and `classStringParser` 71192 * @param value The value to parse/convert to `KeyValueArray` 71193 */ 71194 71195 71196function toStylingKeyValueArray(keyValueArraySet, stringParser, value) { 71197 if (value == null 71198 /*|| value === undefined */ 71199 || value === '') return EMPTY_ARRAY; 71200 const styleKeyValueArray = []; 71201 const unwrappedValue = unwrapSafeValue(value); 71202 71203 if (Array.isArray(unwrappedValue)) { 71204 for (let i = 0; i < unwrappedValue.length; i++) { 71205 keyValueArraySet(styleKeyValueArray, unwrappedValue[i], true); 71206 } 71207 } else if (typeof unwrappedValue === 'object') { 71208 for (const key in unwrappedValue) { 71209 if (unwrappedValue.hasOwnProperty(key)) { 71210 keyValueArraySet(styleKeyValueArray, key, unwrappedValue[key]); 71211 } 71212 } 71213 } else if (typeof unwrappedValue === 'string') { 71214 stringParser(styleKeyValueArray, unwrappedValue); 71215 } else { 71216 ngDevMode && throwError('Unsupported styling type ' + typeof unwrappedValue + ': ' + unwrappedValue); 71217 } 71218 71219 return styleKeyValueArray; 71220} 71221/** 71222 * Set a `value` for a `key`. 71223 * 71224 * See: `keyValueArraySet` for details 71225 * 71226 * @param keyValueArray KeyValueArray to add to. 71227 * @param key Style key to add. 71228 * @param value The value to set. 71229 */ 71230 71231 71232function styleKeyValueArraySet(keyValueArray, key, value) { 71233 keyValueArraySet(keyValueArray, key, unwrapSafeValue(value)); 71234} 71235/** 71236 * Update map based styling. 71237 * 71238 * Map based styling could be anything which contains more than one binding. For example `string`, 71239 * or object literal. Dealing with all of these types would complicate the logic so 71240 * instead this function expects that the complex input is first converted into normalized 71241 * `KeyValueArray`. The advantage of normalization is that we get the values sorted, which makes it 71242 * very cheap to compute deltas between the previous and current value. 71243 * 71244 * @param tView Associated `TView.data` contains the linked list of binding priorities. 71245 * @param tNode `TNode` where the binding is located. 71246 * @param lView `LView` contains the values associated with other styling binding at this `TNode`. 71247 * @param renderer Renderer to use if any updates. 71248 * @param oldKeyValueArray Previous value represented as `KeyValueArray` 71249 * @param newKeyValueArray Current value represented as `KeyValueArray` 71250 * @param isClassBased `true` if `class` (`false` if `style`) 71251 * @param bindingIndex Binding index of the binding. 71252 */ 71253 71254 71255function updateStylingMap(tView, tNode, lView, renderer, oldKeyValueArray, newKeyValueArray, isClassBased, bindingIndex) { 71256 if (oldKeyValueArray === NO_CHANGE) { 71257 // On first execution the oldKeyValueArray is NO_CHANGE => treat it as empty KeyValueArray. 71258 oldKeyValueArray = EMPTY_ARRAY; 71259 } 71260 71261 let oldIndex = 0; 71262 let newIndex = 0; 71263 let oldKey = 0 < oldKeyValueArray.length ? oldKeyValueArray[0] : null; 71264 let newKey = 0 < newKeyValueArray.length ? newKeyValueArray[0] : null; 71265 71266 while (oldKey !== null || newKey !== null) { 71267 ngDevMode && assertLessThan(oldIndex, 999, 'Are we stuck in infinite loop?'); 71268 ngDevMode && assertLessThan(newIndex, 999, 'Are we stuck in infinite loop?'); 71269 const oldValue = oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex + 1] : undefined; 71270 const newValue = newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex + 1] : undefined; 71271 let setKey = null; 71272 let setValue = undefined; 71273 71274 if (oldKey === newKey) { 71275 // UPDATE: Keys are equal => new value is overwriting old value. 71276 oldIndex += 2; 71277 newIndex += 2; 71278 71279 if (oldValue !== newValue) { 71280 setKey = newKey; 71281 setValue = newValue; 71282 } 71283 } else if (newKey === null || oldKey !== null && oldKey < newKey) { 71284 // DELETE: oldKey key is missing or we did not find the oldKey in the newValue 71285 // (because the keyValueArray is sorted and `newKey` is found later alphabetically). 71286 // `"background" < "color"` so we need to delete `"background"` because it is not found in the 71287 // new array. 71288 oldIndex += 2; 71289 setKey = oldKey; 71290 } else { 71291 // CREATE: newKey's is earlier alphabetically than oldKey's (or no oldKey) => we have new key. 71292 // `"color" > "background"` so we need to add `color` because it is in new array but not in 71293 // old array. 71294 ngDevMode && assertDefined(newKey, 'Expecting to have a valid key'); 71295 newIndex += 2; 71296 setKey = newKey; 71297 setValue = newValue; 71298 } 71299 71300 if (setKey !== null) { 71301 updateStyling(tView, tNode, lView, renderer, setKey, setValue, isClassBased, bindingIndex); 71302 } 71303 71304 oldKey = oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex] : null; 71305 newKey = newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex] : null; 71306 } 71307} 71308/** 71309 * Update a simple (property name) styling. 71310 * 71311 * This function takes `prop` and updates the DOM to that value. The function takes the binding 71312 * value as well as binding priority into consideration to determine which value should be written 71313 * to DOM. (For example it may be determined that there is a higher priority overwrite which blocks 71314 * the DOM write, or if the value goes to `undefined` a lower priority overwrite may be consulted.) 71315 * 71316 * @param tView Associated `TView.data` contains the linked list of binding priorities. 71317 * @param tNode `TNode` where the binding is located. 71318 * @param lView `LView` contains the values associated with other styling binding at this `TNode`. 71319 * @param renderer Renderer to use if any updates. 71320 * @param prop Either style property name or a class name. 71321 * @param value Either style value for `prop` or `true`/`false` if `prop` is class. 71322 * @param isClassBased `true` if `class` (`false` if `style`) 71323 * @param bindingIndex Binding index of the binding. 71324 */ 71325 71326 71327function updateStyling(tView, tNode, lView, renderer, prop, value, isClassBased, bindingIndex) { 71328 if (!(tNode.type & 3 71329 /* TNodeType.AnyRNode */ 71330 )) { 71331 // It is possible to have styling on non-elements (such as ng-container). 71332 // This is rare, but it does happen. In such a case, just ignore the binding. 71333 return; 71334 } 71335 71336 const tData = tView.data; 71337 const tRange = tData[bindingIndex + 1]; 71338 const higherPriorityValue = getTStylingRangeNextDuplicate(tRange) ? findStylingValue(tData, tNode, lView, prop, getTStylingRangeNext(tRange), isClassBased) : undefined; 71339 71340 if (!isStylingValuePresent(higherPriorityValue)) { 71341 // We don't have a next duplicate, or we did not find a duplicate value. 71342 if (!isStylingValuePresent(value)) { 71343 // We should delete current value or restore to lower priority value. 71344 if (getTStylingRangePrevDuplicate(tRange)) { 71345 // We have a possible prev duplicate, let's retrieve it. 71346 value = findStylingValue(tData, null, lView, prop, bindingIndex, isClassBased); 71347 } 71348 } 71349 71350 const rNode = getNativeByIndex(getSelectedIndex(), lView); 71351 applyStyling(renderer, isClassBased, rNode, prop, value); 71352 } 71353} 71354/** 71355 * Search for styling value with higher priority which is overwriting current value, or a 71356 * value of lower priority to which we should fall back if the value is `undefined`. 71357 * 71358 * When value is being applied at a location, related values need to be consulted. 71359 * - If there is a higher priority binding, we should be using that one instead. 71360 * For example `<div [style]="{color:exp1}" [style.color]="exp2">` change to `exp1` 71361 * requires that we check `exp2` to see if it is set to value other than `undefined`. 71362 * - If there is a lower priority binding and we are changing to `undefined` 71363 * For example `<div [style]="{color:exp1}" [style.color]="exp2">` change to `exp2` to 71364 * `undefined` requires that we check `exp1` (and static values) and use that as new value. 71365 * 71366 * NOTE: The styling stores two values. 71367 * 1. The raw value which came from the application is stored at `index + 0` location. (This value 71368 * is used for dirty checking). 71369 * 2. The normalized value is stored at `index + 1`. 71370 * 71371 * @param tData `TData` used for traversing the priority. 71372 * @param tNode `TNode` to use for resolving static styling. Also controls search direction. 71373 * - `TNode` search next and quit as soon as `isStylingValuePresent(value)` is true. 71374 * If no value found consult `tNode.residualStyle`/`tNode.residualClass` for default value. 71375 * - `null` search prev and go all the way to end. Return last value where 71376 * `isStylingValuePresent(value)` is true. 71377 * @param lView `LView` used for retrieving the actual values. 71378 * @param prop Property which we are interested in. 71379 * @param index Starting index in the linked list of styling bindings where the search should start. 71380 * @param isClassBased `true` if `class` (`false` if `style`) 71381 */ 71382 71383 71384function findStylingValue(tData, tNode, lView, prop, index, isClassBased) { 71385 // `TNode` to use for resolving static styling. Also controls search direction. 71386 // - `TNode` search next and quit as soon as `isStylingValuePresent(value)` is true. 71387 // If no value found consult `tNode.residualStyle`/`tNode.residualClass` for default value. 71388 // - `null` search prev and go all the way to end. Return last value where 71389 // `isStylingValuePresent(value)` is true. 71390 const isPrevDirection = tNode === null; 71391 let value = undefined; 71392 71393 while (index > 0) { 71394 const rawKey = tData[index]; 71395 const containsStatics = Array.isArray(rawKey); // Unwrap the key if we contain static values. 71396 71397 const key = containsStatics ? rawKey[1] : rawKey; 71398 const isStylingMap = key === null; 71399 let valueAtLViewIndex = lView[index + 1]; 71400 71401 if (valueAtLViewIndex === NO_CHANGE) { 71402 // In firstUpdatePass the styling instructions create a linked list of styling. 71403 // On subsequent passes it is possible for a styling instruction to try to read a binding 71404 // which 71405 // has not yet executed. In that case we will find `NO_CHANGE` and we should assume that 71406 // we have `undefined` (or empty array in case of styling-map instruction) instead. This 71407 // allows the resolution to apply the value (which may later be overwritten when the 71408 // binding actually executes.) 71409 valueAtLViewIndex = isStylingMap ? EMPTY_ARRAY : undefined; 71410 } 71411 71412 let currentValue = isStylingMap ? keyValueArrayGet(valueAtLViewIndex, prop) : key === prop ? valueAtLViewIndex : undefined; 71413 71414 if (containsStatics && !isStylingValuePresent(currentValue)) { 71415 currentValue = keyValueArrayGet(rawKey, prop); 71416 } 71417 71418 if (isStylingValuePresent(currentValue)) { 71419 value = currentValue; 71420 71421 if (isPrevDirection) { 71422 return value; 71423 } 71424 } 71425 71426 const tRange = tData[index + 1]; 71427 index = isPrevDirection ? getTStylingRangePrev(tRange) : getTStylingRangeNext(tRange); 71428 } 71429 71430 if (tNode !== null) { 71431 // in case where we are going in next direction AND we did not find anything, we need to 71432 // consult residual styling 71433 let residual = isClassBased ? tNode.residualClasses : tNode.residualStyles; 71434 71435 if (residual != null 71436 /** OR residual !=== undefined */ 71437 ) { 71438 value = keyValueArrayGet(residual, prop); 71439 } 71440 } 71441 71442 return value; 71443} 71444/** 71445 * Determines if the binding value should be used (or if the value is 'undefined' and hence priority 71446 * resolution should be used.) 71447 * 71448 * @param value Binding style value. 71449 */ 71450 71451 71452function isStylingValuePresent(value) { 71453 // Currently only `undefined` value is considered non-binding. That is `undefined` says I don't 71454 // have an opinion as to what this binding should be and you should consult other bindings by 71455 // priority to determine the valid value. 71456 // This is extracted into a single function so that we have a single place to control this. 71457 return value !== undefined; 71458} 71459/** 71460 * Normalizes and/or adds a suffix to the value. 71461 * 71462 * If value is `null`/`undefined` no suffix is added 71463 * @param value 71464 * @param suffix 71465 */ 71466 71467 71468function normalizeSuffix(value, suffix) { 71469 if (value == null 71470 /** || value === undefined */ 71471 ) {// do nothing 71472 } else if (typeof suffix === 'string') { 71473 value = value + suffix; 71474 } else if (typeof value === 'object') { 71475 value = stringify(unwrapSafeValue(value)); 71476 } 71477 71478 return value; 71479} 71480/** 71481 * Tests if the `TNode` has input shadow. 71482 * 71483 * An input shadow is when a directive steals (shadows) the input by using `@Input('style')` or 71484 * `@Input('class')` as input. 71485 * 71486 * @param tNode `TNode` which we would like to see if it has shadow. 71487 * @param isClassBased `true` if `class` (`false` if `style`) 71488 */ 71489 71490 71491function hasStylingInputShadow(tNode, isClassBased) { 71492 return (tNode.flags & (isClassBased ? 16 71493 /* TNodeFlags.hasClassInput */ 71494 : 32 71495 /* TNodeFlags.hasStyleInput */ 71496 )) !== 0; 71497} 71498/** 71499 * @license 71500 * Copyright Google LLC All Rights Reserved. 71501 * 71502 * Use of this source code is governed by an MIT-style license that can be 71503 * found in the LICENSE file at https://angular.io/license 71504 */ 71505 71506/** 71507 * Create static text node 71508 * 71509 * @param index Index of the node in the data array 71510 * @param value Static string value to write. 71511 * 71512 * @codeGenApi 71513 */ 71514 71515 71516function ɵɵtext(index, value = '') { 71517 const lView = getLView(); 71518 const tView = getTView(); 71519 const adjustedIndex = index + HEADER_OFFSET; 71520 ngDevMode && assertEqual(getBindingIndex(), tView.bindingStartIndex, 'text nodes should be created before any bindings'); 71521 ngDevMode && assertIndexInRange(lView, adjustedIndex); 71522 const tNode = tView.firstCreatePass ? getOrCreateTNode(tView, adjustedIndex, 1 71523 /* TNodeType.Text */ 71524 , value, null) : tView.data[adjustedIndex]; 71525 const textNative = lView[adjustedIndex] = createTextNode(lView[RENDERER], value); 71526 appendChild(tView, lView, textNative, tNode); // Text nodes are self closing. 71527 71528 setCurrentTNode(tNode, false); 71529} 71530/** 71531 * @license 71532 * Copyright Google LLC All Rights Reserved. 71533 * 71534 * Use of this source code is governed by an MIT-style license that can be 71535 * found in the LICENSE file at https://angular.io/license 71536 */ 71537 71538/** 71539 * 71540 * Update text content with a lone bound value 71541 * 71542 * Used when a text node has 1 interpolated value in it, an no additional text 71543 * surrounds that interpolated value: 71544 * 71545 * ```html 71546 * <div>{{v0}}</div> 71547 * ``` 71548 * 71549 * Its compiled representation is: 71550 * 71551 * ```ts 71552 * ɵɵtextInterpolate(v0); 71553 * ``` 71554 * @returns itself, so that it may be chained. 71555 * @see textInterpolateV 71556 * @codeGenApi 71557 */ 71558 71559 71560function ɵɵtextInterpolate(v0) { 71561 ɵɵtextInterpolate1('', v0, ''); 71562 return ɵɵtextInterpolate; 71563} 71564/** 71565 * 71566 * Update text content with single bound value surrounded by other text. 71567 * 71568 * Used when a text node has 1 interpolated value in it: 71569 * 71570 * ```html 71571 * <div>prefix{{v0}}suffix</div> 71572 * ``` 71573 * 71574 * Its compiled representation is: 71575 * 71576 * ```ts 71577 * ɵɵtextInterpolate1('prefix', v0, 'suffix'); 71578 * ``` 71579 * @returns itself, so that it may be chained. 71580 * @see textInterpolateV 71581 * @codeGenApi 71582 */ 71583 71584 71585function ɵɵtextInterpolate1(prefix, v0, suffix) { 71586 const lView = getLView(); 71587 const interpolated = interpolation1(lView, prefix, v0, suffix); 71588 71589 if (interpolated !== NO_CHANGE) { 71590 textBindingInternal(lView, getSelectedIndex(), interpolated); 71591 } 71592 71593 return ɵɵtextInterpolate1; 71594} 71595/** 71596 * 71597 * Update text content with 2 bound values surrounded by other text. 71598 * 71599 * Used when a text node has 2 interpolated values in it: 71600 * 71601 * ```html 71602 * <div>prefix{{v0}}-{{v1}}suffix</div> 71603 * ``` 71604 * 71605 * Its compiled representation is: 71606 * 71607 * ```ts 71608 * ɵɵtextInterpolate2('prefix', v0, '-', v1, 'suffix'); 71609 * ``` 71610 * @returns itself, so that it may be chained. 71611 * @see textInterpolateV 71612 * @codeGenApi 71613 */ 71614 71615 71616function ɵɵtextInterpolate2(prefix, v0, i0, v1, suffix) { 71617 const lView = getLView(); 71618 const interpolated = interpolation2(lView, prefix, v0, i0, v1, suffix); 71619 71620 if (interpolated !== NO_CHANGE) { 71621 textBindingInternal(lView, getSelectedIndex(), interpolated); 71622 } 71623 71624 return ɵɵtextInterpolate2; 71625} 71626/** 71627 * 71628 * Update text content with 3 bound values surrounded by other text. 71629 * 71630 * Used when a text node has 3 interpolated values in it: 71631 * 71632 * ```html 71633 * <div>prefix{{v0}}-{{v1}}-{{v2}}suffix</div> 71634 * ``` 71635 * 71636 * Its compiled representation is: 71637 * 71638 * ```ts 71639 * ɵɵtextInterpolate3( 71640 * 'prefix', v0, '-', v1, '-', v2, 'suffix'); 71641 * ``` 71642 * @returns itself, so that it may be chained. 71643 * @see textInterpolateV 71644 * @codeGenApi 71645 */ 71646 71647 71648function ɵɵtextInterpolate3(prefix, v0, i0, v1, i1, v2, suffix
71648) { 71649 const lView = getLView(); 71650 const interpolated = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix); 71651 71652 if (interpolated !== NO_CHANGE) { 71653 textBindingInternal(lView, getSelectedIndex(), interpolated); 71654 } 71655 71656 return ɵɵtextInterpolate3; 71657} 71658/** 71659 * 71660 * Update text content with 4 bound values surrounded by other text. 71661 * 71662 * Used when a text node has 4 interpolated values in it: 71663 * 71664 * ```html 71665 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix</div> 71666 * ``` 71667 * 71668 * Its compiled representation is: 71669 * 71670 * ```ts 71671 * ɵɵtextInterpolate4( 71672 * 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix'); 71673 * ``` 71674 * @returns itself, so that it may be chained. 71675 * @see ɵɵtextInterpolateV 71676 * @codeGenApi 71677 */ 71678 71679 71680function ɵɵtextInterpolate4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix) { 71681 const lView = getLView(); 71682 const interpolated = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix); 71683 71684 if (interpolated !== NO_CHANGE) { 71685 textBindingInternal(lView, getSelectedIndex(), interpolated); 71686 } 71687 71688 return ɵɵtextInterpolate4; 71689} 71690/** 71691 * 71692 * Update text content with 5 bound values surrounded by other text. 71693 * 71694 * Used when a text node has 5 interpolated values in it: 71695 * 71696 * ```html 71697 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix</div> 71698 * ``` 71699 * 71700 * Its compiled representation is: 71701 * 71702 * ```ts 71703 * ɵɵtextInterpolate5( 71704 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix'); 71705 * ``` 71706 * @returns itself, so that it may be chained. 71707 * @see textInterpolateV 71708 * @codeGenApi 71709 */ 71710 71711 71712function ɵɵtextInterpolate5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) { 71713 const lView = getLView(); 71714 const interpolated = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix); 71715 71716 if (interpolated !== NO_CHANGE) { 71717 textBindingInternal(lView, getSelectedIndex(), interpolated); 71718 } 71719 71720 return ɵɵtextInterpolate5; 71721} 71722/** 71723 * 71724 * Update text content with 6 bound values surrounded by other text. 71725 * 71726 * Used when a text node has 6 interpolated values in it: 71727 * 71728 * ```html 71729 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix</div> 71730 * ``` 71731 * 71732 * Its compiled representation is: 71733 * 71734 * ```ts 71735 * ɵɵtextInterpolate6( 71736 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix'); 71737 * ``` 71738 * 71739 * @param i4 Static value used for concatenation only. 71740 * @param v5 Value checked for change. @returns itself, so that it may be chained. 71741 * @see textInterpolateV 71742 * @codeGenApi 71743 */ 71744 71745 71746function ɵɵtextInterpolate6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) { 71747 const lView = getLView(); 71748 const interpolated = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix); 71749 71750 if (interpolated !== NO_CHANGE) { 71751 textBindingInternal(lView, getSelectedIndex(), interpolated); 71752 } 71753 71754 return ɵɵtextInterpolate6; 71755} 71756/** 71757 * 71758 * Update text content with 7 bound values surrounded by other text. 71759 * 71760 * Used when a text node has 7 interpolated values in it: 71761 * 71762 * ```html 71763 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix</div> 71764 * ``` 71765 * 71766 * Its compiled representation is: 71767 * 71768 * ```ts 71769 * ɵɵtextInterpolate7( 71770 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix'); 71771 * ``` 71772 * @returns itself, so that it may be chained. 71773 * @see textInterpolateV 71774 * @codeGenApi 71775 */ 71776 71777 71778function ɵɵtextInterpolate7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) { 71779 const lView = getLView(); 71780 const interpolated = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix); 71781 71782 if (interpolated !== NO_CHANGE) { 71783 textBindingInternal(lView, getSelectedIndex(), interpolated); 71784 } 71785 71786 return ɵɵtextInterpolate7; 71787} 71788/** 71789 * 71790 * Update text content with 8 bound values surrounded by other text. 71791 * 71792 * Used when a text node has 8 interpolated values in it: 71793 * 71794 * ```html 71795 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix</div> 71796 * ``` 71797 * 71798 * Its compiled representation is: 71799 * 71800 * ```ts 71801 * ɵɵtextInterpolate8( 71802 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix'); 71803 * ``` 71804 * @returns itself, so that it may be chained. 71805 * @see textInterpolateV 71806 * @codeGenApi 71807 */ 71808 71809 71810function ɵɵtextInterpolate8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) { 71811 const lView = getLView(); 71812 const interpolated = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix); 71813 71814 if (interpolated !== NO_CHANGE) { 71815 textBindingInternal(lView, getSelectedIndex(), interpolated); 71816 } 71817 71818 return ɵɵtextInterpolate8; 71819} 71820/** 71821 * Update text content with 9 or more bound values other surrounded by text. 71822 * 71823 * Used when the number of interpolated values exceeds 8. 71824 * 71825 * ```html 71826 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix</div> 71827 * ``` 71828 * 71829 * Its compiled representation is: 71830 * 71831 * ```ts 71832 * ɵɵtextInterpolateV( 71833 * ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9, 71834 * 'suffix']); 71835 * ``` 71836 *. 71837 * @param values The collection of values and the strings in between those values, beginning with 71838 * a string prefix and ending with a string suffix. 71839 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`) 71840 * 71841 * @returns itself, so that it may be chained. 71842 * @codeGenApi 71843 */ 71844 71845 71846function ɵɵtextInterpolateV(values) { 71847 const lView = getLView(); 71848 const interpolated = interpolationV(lView, values); 71849 71850 if (interpolated !== NO_CHANGE) { 71851 textBindingInternal(lView, getSelectedIndex(), interpolated); 71852 } 71853 71854 return ɵɵtextInterpolateV; 71855} 71856/** 71857 * @license 71858 * Copyright Google LLC All Rights Reserved. 71859 * 71860 * Use of this source code is governed by an MIT-style license that can be 71861 * found in the LICENSE file at https://angular.io/license 71862 */ 71863 71864/** 71865 * 71866 * Update an interpolated class on an element with single bound value surrounded by text. 71867 * 71868 * Used when the value passed to a property has 1 interpolated value in it: 71869 * 71870 * ```html 71871 * <div class="prefix{{v0}}suffix"></div> 71872 * ``` 71873 * 71874 * Its compiled representation is: 71875 * 71876 * ```ts 71877 * ɵɵclassMapInterpolate1('prefix', v0, 'suffix'); 71878 * ``` 71879 *
71880 * @param prefix Static value used for concatenation only. 71881 * @param v0 Value checked for change. 71882 * @param suffix Static value used for concatenation only. 71883 * @codeGenApi 71884 */ 71885 71886 71887function ɵɵclassMapInterpolate1(prefix, v0, suffix) { 71888 const lView = getLView(); 71889 const interpolatedValue = interpolation1(lView, prefix, v0, suffix); 71890 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true); 71891} 71892/** 71893 * 71894 * Update an interpolated class on an element with 2 bound values surrounded by text. 71895 * 71896 * Used when the value passed to a property has 2 interpolated values in it: 71897 * 71898 * ```html 71899 * <div class="prefix{{v0}}-{{v1}}suffix"></div> 71900 * ``` 71901 * 71902 * Its compiled representation is: 71903 * 71904 * ```ts 71905 * ɵɵclassMapInterpolate2('prefix', v0, '-', v1, 'suffix'); 71906 * ``` 71907 * 71908 * @param prefix Static value used for concatenation only. 71909 * @param v0 Value checked for change. 71910 * @param i0 Static value used for concatenation only. 71911 * @param v1 Value checked for change. 71912 * @param suffix Static value used for concatenation only. 71913 * @codeGenApi 71914 */ 71915 71916 71917function ɵɵclassMapInterpolate2(prefix, v0, i0, v1, suffix) { 71918 const lView = getLView(); 71919 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix); 71920 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true); 71921} 71922/** 71923 * 71924 * Update an interpolated class on an element with 3 bound values surrounded by text. 71925 * 71926 * Used when the value passed to a property has 3 interpolated values in it: 71927 * 71928 * ```html 71929 * <div class="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div> 71930 * ``` 71931 * 71932 * Its compiled representation is: 71933 * 71934 * ```ts 71935 * ɵɵclassMapInterpolate3( 71936 * 'prefix', v0, '-', v1, '-', v2, 'suffix'); 71937 * ``` 71938 * 71939 * @param prefix Static value used for concatenation only. 71940 * @param v0 Value checked for change. 71941 * @param i0 Static value used for concatenation only. 71942 * @param v1 Value checked for change. 71943 * @param i1 Static value used for concatenation only. 71944 * @param v2 Value checked for change. 71945 * @param suffix Static value used for concatenation only. 71946 * @codeGenApi 71947 */ 71948 71949 71950function ɵɵclassMapInterpolate3(prefix, v0, i0, v1, i1, v2, suffix) { 71951 const lView = getLView(); 71952 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix); 71953 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true); 71954} 71955/** 71956 * 71957 * Update an interpolated class on an element with 4 bound values surrounded by text. 71958 * 71959 * Used when the value passed to a property has 4 interpolated values in it: 71960 * 71961 * ```html 71962 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div> 71963 * ``` 71964 * 71965 * Its compiled representation is: 71966 * 71967 * ```ts 71968 * ɵɵclassMapInterpolate4( 71969 * 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix'); 71970 * ``` 71971 * 71972 * @param prefix Static value used for concatenation only. 71973 * @param v0 Value checked for change. 71974 * @param i0 Static value used for concatenation only. 71975 * @param v1 Value checked for change. 71976 * @param i1 Static value used for concatenation only. 71977 * @param v2 Value checked for change. 71978 * @param i2 Static value used for concatenation only. 71979 * @param v3 Value checked for change. 71980 * @param suffix Static value used for concatenation only. 71981 * @codeGenApi 71982 */ 71983 71984 71985function ɵɵclassMapInterpolate4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix) { 71986 const lView = getLView(); 71987 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix); 71988 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true); 71989} 71990/** 71991 * 71992 * Update an interpolated class on an element with 5 bound values surrounded by text. 71993 * 71994 * Used when the value passed to a property has 5 interpolated values in it: 71995 * 71996 * ```html 71997 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div> 71998 * ``` 71999 * 72000 * Its compiled representation is: 72001 * 72002 * ```ts 72003 * ɵɵclassMapInterpolate5( 72004 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix'); 72005 * ``` 72006 * 72007 * @param prefix Static value used for concatenation only. 72008 * @param v0 Value checked for change. 72009 * @param i0 Static value used for concatenation only. 72010 * @param v1 Value checked for change.
72011 * @param i1 Static value used for concatenation only. 72012 * @param v2 Value checked for change. 72013 * @param i2 Static value used for concatenation only. 72014 * @param v3 Value checked for change. 72015 * @param i3 Static value used for concatenation only. 72016 * @param v4 Value checked for change. 72017 * @param suffix Static value used for concatenation only. 72018 * @codeGenApi 72019 */ 72020 72021 72022function ɵɵclassMapInterpolate5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) { 72023 const lView = getLView(); 72024 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix); 72025 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true); 72026} 72027/** 72028 * 72029 * Update an interpolated class on an element with 6 bound values surrounded by text. 72030 * 72031 * Used when the value passed to a property has 6 interpolated values in it: 72032 * 72033 * ```html 72034 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div> 72035 * ``` 72036 * 72037 * Its compiled representation is: 72038 * 72039 * ```ts 72040 * ɵɵclassMapInterpolate6( 72041 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix'); 72042 * ``` 72043 * 72044 * @param prefix Static value used for concatenation only. 72045 * @param v0 Value checked for change. 72046 * @param i0 Static value used for concatenation only. 72047 * @param v1 Value checked for change. 72048 * @param i1 Static value used for concatenation only. 72049 * @param v2 Value checked for change. 72050 * @param i2 Static value used for concatenation only. 72051 * @param v3 Value checked for change. 72052 * @param i3 Static value used for concatenation only. 72053 * @param v4 Value checked for change. 72054 * @param i4 Static value used for concatenation only. 72055 * @param v5 Value checked for change. 72056 * @param suffix Static value used for concatenation only. 72057 * @codeGenApi 72058 */ 72059 72060 72061function ɵɵclassMapInterpolate6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) { 72062 const lView = getLView(); 72063 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix); 72064 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true); 72065} 72066/** 72067 * 72068 * Update an interpolated class on an element with 7 bound values surrounded by text. 72069 * 72070 * Used when the value passed to a property has 7 interpolated values in it: 72071 * 72072 * ```html 72073 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div> 72074 * ``` 72075 * 72076 * Its compiled representation is: 72077 * 72078 * ```ts 72079 * ɵɵclassMapInterpolate7( 72080 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix'); 72081 * ``` 72082 * 72083 * @param prefix Static value used for concatenation only. 72084 * @param v0 Value checked for change. 72085 * @param i0 Static value used for concatenation only. 72086 * @param v1 Value checked for change. 72087 * @param i1 Static value used for concatenation only. 72088 * @param v2 Value checked for change. 72089 * @param i2 Static value used for concatenation only. 72090 * @param v3 Value checked for change. 72091 * @param i3 Static value used for concatenation only. 72092 * @param v4 Value checked for change. 72093 * @param i4 Static value used for concatenation only. 72094 * @param v5 Value checked for change. 72095 * @param i5 Static value used for concatenation only. 72096 * @param v6 Value checked for change. 72097 * @param suffix Static value used for concatenation only. 72098 * @codeGenApi 72099 */ 72100 72101 72102function ɵɵclassMapInterpolate7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) { 72103 const lView = getLView(); 72104 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix); 72105 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true); 72106} 72107/** 72108 * 72109 * Update an interpolated class on an element with 8 bound values surrounded by text. 72110 * 72111 * Used when the value passed to a property has 8 interpolated values in it: 72112 * 72113 * ```html 72114 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div> 72115 * ``` 72116 * 72117 * Its compiled representation is: 72118 * 72119 * ```ts 72120 * ɵɵclassMapInterpolate8( 72121 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix'); 72122 * ``` 72123 *
72124 * @param prefix Static value used for concatenation only. 72125 * @param v0 Value checked for change. 72126 * @param i0 Static value used for concatenation only. 72127 * @param v1 Value checked for change. 72128 * @param i1 Static value used for concatenation only. 72129 * @param v2 Value checked for change. 72130 * @param i2 Static value used for concatenation only. 72131 * @param v3 Value checked for change. 72132 * @param i3 Static value used for concatenation only. 72133 * @param v4 Value checked for change. 72134 * @param i4 Static value used for concatenation only. 72135 * @param v5 Value checked for change. 72136 * @param i5 Static value used for concatenation only. 72137 * @param v6 Value checked for change. 72138 * @param i6 Static value used for concatenation only. 72139 * @param v7 Value checked for change. 72140 * @param suffix Static value used for concatenation only. 72141 * @codeGenApi 72142 */ 72143 72144 72145function ɵɵclassMapInterpolate8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) { 72146 const lView = getLView(); 72147 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix); 72148 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true); 72149} 72150/** 72151 * Update an interpolated class on an element with 9 or more bound values surrounded by text. 72152 * 72153 * Used when the number of interpolated values exceeds 8. 72154 * 72155 * ```html 72156 * <div 72157 * class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"></div> 72158 * ``` 72159 * 72160 * Its compiled representation is: 72161 * 72162 * ```ts 72163 * ɵɵclassMapInterpolateV( 72164 * ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9, 72165 * 'suffix']); 72166 * ``` 72167 *. 72168 * @param values The collection of values and the strings in-between those values, beginning with 72169 * a string prefix and ending with a string suffix. 72170 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`) 72171 * @codeGenApi 72172 */ 72173 72174 72175function ɵɵclassMapInterpolateV(values) { 72176 const lView = getLView(); 72177 const interpolatedValue = interpolationV(lView, values); 72178 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true); 72179} 72180/** 72181 * @license 72182 * Copyright Google LLC All Rights Reserved. 72183 * 72184 * Use of this source code is governed by an MIT-style license that can be 72185 * found in the LICENSE file at https://angular.io/license 72186 */ 72187 72188/** 72189 * 72190 * Update an interpolated style on an element with single bound value surrounded by text. 72191 * 72192 * Used when the value passed to a property has 1 interpolated value in it: 72193 * 72194 * ```html 72195 * <div style="key: {{v0}}suffix"></div> 72196 * ``` 72197 * 72198 * Its compiled representation is: 72199 * 72200 * ```ts 72201 * ɵɵstyleMapInterpolate1('key: ', v0, 'suffix'); 72202 * ``` 72203 * 72204 * @param prefix Static value used for concatenation only. 72205 * @param v0 Value checked for change. 72206 * @param suffix Static value used for concatenation only. 72207 * @codeGenApi 72208 */ 72209 72210 72211function ɵɵstyleMapInterpolate1(prefix, v0, suffix) { 72212 const lView = getLView(); 72213 const interpolatedValue = interpolation1(lView, prefix, v0, suffix); 72214 ɵɵstyleMap(interpolatedValue); 72215} 72216/** 72217 * 72218 * Update an interpolated style on an element with 2 bound values surrounded by text. 72219 * 72220 * Used when the value passed to a property has 2 interpolated values in it: 72221 * 72222 * ```html 72223 * <div style="key: {{v0}}; key1: {{v1}}suffix"></div> 72224 * ``` 72225 * 72226 * Its compiled representation is: 72227 * 72228 * ```ts 72229 * ɵɵstyleMapInterpolate2('key: ', v0, '; key1: ', v1, 'suffix'); 72230 * ``` 72231 * 72232 * @param prefix Static value used for concatenation only. 72233 * @param v0 Value checked for change. 72234 * @param i0 Static value used for concatenation only. 72235 * @param v1 Value checked for change. 72236 * @param suffix Static value used for concatenation only. 72237 * @codeGenApi 72238 */ 72239 72240 72241function ɵɵstyleMapInterpolate2(prefix, v0, i0, v1, suffix) { 72242 const lView = getLView(); 72243 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix); 72244 ɵɵstyleMap(interpolatedValue); 72245} 72246/** 72247 * 72248 * Update an interpolated style on an element with 3 bound values surrounded by text. 72249 * 72250 * Used when the value passed to a property has 3 interpolated values in it: 72251 * 72252 * ```html 72253 * <div style="key: {{v0}}; key2: {{v1}}; key2: {{v2}}suffix"></div> 72254 * ``` 72255 * 72256 * Its compiled representation is: 72257 * 72258 * ```ts 72259 * ɵɵstyleMapInterpolate3( 72260 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, 'suffix'); 72261 * ``` 72262 *
72263 * @param prefix Static value used for concatenation only. 72264 * @param v0 Value checked for change. 72265 * @param i0 Static value used for concatenation only. 72266 * @param v1 Value checked for change. 72267 * @param i1 Static value used for concatenation only. 72268 * @param v2 Value checked for change. 72269 * @param suffix Static value used for concatenation only. 72270 * @codeGenApi 72271 */ 72272 72273 72274function ɵɵstyleMapInterpolate3(prefix, v0, i0, v1, i1, v2, suffix) { 72275 const lView = getLView(); 72276 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix); 72277 ɵɵstyleMap(interpolatedValue); 72278} 72279/** 72280 * 72281 * Update an interpolated style on an element with 4 bound values surrounded by text. 72282 * 72283 * Used when the value passed to a property has 4 interpolated values in it: 72284 * 72285 * ```html 72286 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}suffix"></div> 72287 * ``` 72288 * 72289 * Its compiled representation is: 72290 * 72291 * ```ts 72292 * ɵɵstyleMapInterpolate4( 72293 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, 'suffix'); 72294 * ``` 72295 * 72296 * @param prefix Static value used for concatenation only. 72297 * @param v0 Value checked for change. 72298 * @param i0 Static value used for concatenation only. 72299 * @param v1 Value checked for change. 72300 * @param i1 Static value used for concatenation only. 72301 * @param v2 Value checked for change. 72302 * @param i2 Static value used for concatenation only. 72303 * @param v3 Value checked for change. 72304 * @param suffix Static value used for concatenation only. 72305 * @codeGenApi 72306 */ 72307 72308 72309function ɵɵstyleMapInterpolate4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix) { 72310 const lView = getLView(); 72311 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix); 72312 ɵɵstyleMap(interpolatedValue); 72313} 72314/** 72315 * 72316 * Update an interpolated style on an element with 5 bound values surrounded by text. 72317 * 72318 * Used when the value passed to a property has 5 interpolated values in it: 72319 * 72320 * ```html 72321 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}suffix"></div> 72322 * ``` 72323 * 72324 * Its compiled representation is: 72325 * 72326 * ```ts 72327 * ɵɵstyleMapInterpolate5( 72328 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, 'suffix'); 72329 * ``` 72330 * 72331 * @param prefix Static value used for concatenation only. 72332 * @param v0 Value checked for change. 72333 * @param i0 Static value used for concatenation only. 72334 * @param v1 Value checked for change. 72335 * @param i1 Static value used for concatenation only. 72336 * @param v2 Value checked for change. 72337 * @param i2 Static value used for concatenation only. 72338 * @param v3 Value checked for change. 72339 * @param i3 Static value used for concatenation only. 72340 * @param v4 Value checked for change. 72341 * @param suffix Static value used for concatenation only. 72342 * @codeGenApi 72343 */ 72344 72345 72346function ɵɵstyleMapInterpolate5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) { 72347 const lView = getLView(); 72348 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix); 72349 ɵɵstyleMap(interpolatedValue); 72350} 72351/** 72352 * 72353 * Update an interpolated style on an element with 6 bound values surrounded by text. 72354 * 72355 * Used when the value passed to a property has 6 interpolated values in it: 72356 * 72357 * ```html 72358 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; 72359 * key5: {{v5}}suffix"></div> 72360 * ``` 72361 * 72362 * Its compiled representation is: 72363 * 72364 * ```ts 72365 * ɵɵstyleMapInterpolate6( 72366 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5, 72367 * 'suffix'); 72368 * ``` 72369 * 72370 * @param prefix Static value used for concatenation only. 72371 * @param v0 Value checked for change. 72372 * @param i0 Static value used for concatenation only. 72373 * @param v1 Value checked for change. 72374 * @param i1 Static value used for concatenation only. 72375 * @param v2 Value checked for change. 72376 * @param i2 Static value used for concatenation only. 72377 * @param v3 Value checked for change. 72378 * @param i3 Static value used for concatenation only. 72379 * @param v4 Value checked for change. 72380 * @param i4 Static value used for concatenation only. 72381 * @param v5 Value checked for change.
72382 * @param suffix Static value used for concatenation only. 72383 * @codeGenApi 72384 */ 72385 72386 72387function ɵɵstyleMapInterpolate6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) { 72388 const lView = getLView(); 72389 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix); 72390 ɵɵstyleMap(interpolatedValue); 72391} 72392/** 72393 * 72394 * Update an interpolated style on an element with 7 bound values surrounded by text. 72395 * 72396 * Used when the value passed to a property has 7 interpolated values in it: 72397 * 72398 * ```html 72399 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}}; 72400 * key6: {{v6}}suffix"></div> 72401 * ``` 72402 * 72403 * Its compiled representation is: 72404 * 72405 * ```ts 72406 * ɵɵstyleMapInterpolate7( 72407 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5, 72408 * '; key6: ', v6, 'suffix'); 72409 * ``` 72410 * 72411 * @param prefix Static value used for concatenation only. 72412 * @param v0 Value checked for change. 72413 * @param i0 Static value used for concatenation only. 72414 * @param v1 Value checked for change. 72415 * @param i1 Static value used for concatenation only. 72416 * @param v2 Value checked for change. 72417 * @param i2 Static value used for concatenation only. 72418 * @param v3 Value checked for change. 72419 * @param i3 Static value used for concatenation only. 72420 * @param v4 Value checked for change. 72421 * @param i4 Static value used for concatenation only. 72422 * @param v5 Value checked for change. 72423 * @param i5 Static value used for concatenation only. 72424 * @param v6 Value checked for change. 72425 * @param suffix Static value used for concatenation only. 72426 * @codeGenApi 72427 */ 72428 72429 72430function ɵɵstyleMapInterpolate7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) { 72431 const lView = getLView(); 72432 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix); 72433 ɵɵstyleMap(interpolatedValue); 72434} 72435/** 72436 * 72437 * Update an interpolated style on an element with 8 bound values surrounded by text. 72438 * 72439 * Used when the value passed to a property has 8 interpolated values in it: 72440 * 72441 * ```html 72442 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}}; 72443 * key6: {{v6}}; key7: {{v7}}suffix"></div> 72444 * ``` 72445 * 72446 * Its compiled representation is: 72447 * 72448 * ```ts 72449 * ɵɵstyleMapInterpolate8( 72450 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5, 72451 * '; key6: ', v6, '; key7: ', v7, 'suffix'); 72452 * ``` 72453 * 72454 * @param prefix Static value used for concatenation only. 72455 * @param v0 Value checked for change. 72456 * @param i0 Static value used for concatenation only. 72457 * @param v1 Value checked for change. 72458 * @param i1 Static value used for concatenation only. 72459 * @param v2 Value checked for change. 72460 * @param i2 Static value used for concatenation only. 72461 * @param v3 Value checked for change. 72462 * @param i3 Static value used for concatenation only. 72463 * @param v4 Value checked for change. 72464 * @param i4 Static value used for concatenation only. 72465 * @param v5 Value checked for change. 72466 * @param i5 Static value used for concatenation only. 72467 * @param v6 Value checked for change. 72468 * @param i6 Static value used for concatenation only. 72469 * @param v7 Value checked for change. 72470 * @param suffix Static value used for concatenation only. 72471 * @codeGenApi 72472 */ 72473 72474 72475function ɵɵstyleMapInterpolate8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) { 72476 const lView = getLView(); 72477 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix); 72478 ɵɵstyleMap(interpolatedValue); 72479} 72480/** 72481 * Update an interpolated style on an element with 9 or more bound values surrounded by text. 72482 * 72483 * Used when the number of interpolated values exceeds 8. 72484 * 72485 * ```html 72486 * <div 72487 * class="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}}; 72488 * key6: {{v6}}; key7: {{v7}}; key8: {{v8}}; key9: {{v9}}suffix"></div> 72489 * ``` 72490 * 72491 * Its compiled representation is: 72492 * 72493 * ```ts 72494 * ɵɵstyleMapInterpolateV( 72495 * ['key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5, 72496 * '; key6: ', v6, '; key7: ', v7, '; key8: ', v8, '; key9: ', v9, 'suffix']); 72497 * ``` 72498 *. 72499 * @param values The collection of values and the strings in-between those values, beginning with 72500 * a string prefix and ending with a string suffix. 72501 * (e.g. `['prefix', value0, '; key2: ', value1, '; key2: ', value2, ..., value99, 'suffix']`) 72502 * @codeGenApi 72503 */ 72504 72505 72506function ɵɵstyleMapInterpolateV(values) { 72507 const lView = getLView(); 72508 const interpolatedValue = interpolationV(lView, values); 72509 ɵɵstyleMap(interpolatedValue); 72510} 72511/** 72512 * @license 72513 * Copyright Google LLC All Rights Reserved. 72514 * 72515 * Use of this source code is governed by an MIT-style license that can be 72516 * found in the LICENSE file at https://angular.io/license 72517 */ 72518 72519/** 72520 * 72521 * Update an interpolated style property on an element with single bound value surrounded by text. 72522 * 72523 * Used when the value passed to a property has 1 interpolated value in it: 72524 * 72525 * ```html 72526 * <div style.color="prefix{{v0}}suffix"></div> 72527 * ``` 72528 * 72529 * Its compiled representation is: 72530 * 72531 * ```ts 72532 * ɵɵstylePropInterpolate1(0, 'prefix', v0, 'suffix'); 72533 * ``` 72534 * 72535 * @param styleIndex Index of style to update. This index value refers to the 72536 * index of the style in the style bindings array that was passed into 72537 * `styling`.
72538 * @param prefix Static value used for concatenation only. 72539 * @param v0 Value checked for change. 72540 * @param suffix Static value used for concatenation only. 72541 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`. 72542 * @returns itself, so that it may be chained. 72543 * @codeGenApi 72544 */ 72545 72546 72547function ɵɵstylePropInterpolate1(prop, prefix, v0, suffix, valueSuffix) { 72548 const lView = getLView(); 72549 const interpolatedValue = interpolation1(lView, prefix, v0, suffix); 72550 checkStylingProperty(prop, interpolatedValue, valueSuffix, false); 72551 return ɵɵstylePropInterpolate1; 72552} 72553/** 72554 * 72555 * Update an interpolated style property on an element with 2 bound values surrounded by text. 72556 * 72557 * Used when the value passed to a property has 2 interpolated values in it: 72558 * 72559 * ```html 72560 * <div style.color="prefix{{v0}}-{{v1}}suffix"></div> 72561 * ``` 72562 * 72563 * Its compiled representation is: 72564 * 72565 * ```ts 72566 * ɵɵstylePropInterpolate2(0, 'prefix', v0, '-', v1, 'suffix'); 72567 * ``` 72568 * 72569 * @param styleIndex Index of style to update. This index value refers to the 72570 * index of the style in the style bindings array that was passed into 72571 * `styling`. 72572 * @param prefix Static value used for concatenation only. 72573 * @param v0 Value checked for change. 72574 * @param i0 Static value used for concatenation only. 72575 * @param v1 Value checked for change. 72576 * @param suffix Static value used for concatenation only. 72577 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`. 72578 * @returns itself, so that it may be chained. 72579 * @codeGenApi 72580 */ 72581 72582 72583function ɵɵstylePropInterpolate2(prop, prefix, v0, i0, v1, suffix, valueSuffix) { 72584 const lView = getLView(); 72585 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix); 72586 checkStylingProperty(prop, interpolatedValue, valueSuffix, false); 72587 return ɵɵstylePropInterpolate2; 72588} 72589/** 72590 * 72591 * Update an interpolated style property on an element with 3 bound values surrounded by text. 72592 * 72593 * Used when the value passed to a property has 3 interpolated values in it: 72594 * 72595 * ```html 72596 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div> 72597 * ``` 72598 * 72599 * Its compiled representation is: 72600 * 72601 * ```ts 72602 * ɵɵstylePropInterpolate3(0, 'prefix', v0, '-', v1, '-', v2, 'suffix'); 72603 * ``` 72604 * 72605 * @param styleIndex Index of style to update. This index value refers to the 72606 * index of the style in the style bindings array that was passed into 72607 * `styling`. 72608 * @param prefix Static value used for concatenation only. 72609 * @param v0 Value checked for change. 72610 * @param i0 Static value used for concatenation only. 72611 * @param v1 Value checked for change. 72612 * @param i1 Static value used for concatenation only. 72613 * @param v2 Value checked for change. 72614 * @param suffix Static value used for concatenation only. 72615 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`. 72616 * @returns itself, so that it may be chained. 72617 * @codeGenApi 72618 */ 72619 72620 72621function ɵɵstylePropInterpolate3(prop, prefix, v0, i0, v1, i1, v2, suffix, valueSuffix) { 72622 const lView = getLView(); 72623 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix); 72624 checkStylingProperty(prop, interpolatedValue, valueSuffix, false); 72625 return ɵɵstylePropInterpolate3; 72626} 72627/** 72628 * 72629 * Update an interpolated style property on an element with 4 bound values surrounded by text. 72630 * 72631 * Used when the value passed to a property has 4 interpolated values in it: 72632 * 72633 * ```html 72634 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div> 72635 * ``` 72636 * 72637 * Its compiled representation is: 72638 * 72639 * ```ts 72640 * ɵɵstylePropInterpolate4(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix'); 72641 * ``` 72642 * 72643 * @param styleIndex Index of style to update. This index value refers to the 72644 * index of the style in the style bindings array that was passed into 72645 * `styling`. 72646 * @param prefix Static value used for concatenation only. 72647 * @param v0 Value checked for change. 72648 * @param i0 Static value used for concatenation only. 72649 * @param v1 Value checked for change. 72650 * @param i1 Static value used for concatenation only. 72651 * @param v2 Value checked for change.
72652 * @param i2 Static value used for concatenation only. 72653 * @param v3 Value checked for change. 72654 * @param suffix Static value used for concatenation only. 72655 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`. 72656 * @returns itself, so that it may be chained. 72657 * @codeGenApi 72658 */ 72659 72660 72661function ɵɵstylePropInterpolate4(prop, prefix, v0, i0, v1, i1, v2, i2, v3, suffix, valueSuffix) { 72662 const lView = getLView(); 72663 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix); 72664 checkStylingProperty(prop, interpolatedValue, valueSuffix, false); 72665 return ɵɵstylePropInterpolate4; 72666} 72667/** 72668 * 72669 * Update an interpolated style property on an element with 5 bound values surrounded by text. 72670 * 72671 * Used when the value passed to a property has 5 interpolated values in it: 72672 * 72673 * ```html 72674 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div> 72675 * ``` 72676 * 72677 * Its compiled representation is: 72678 * 72679 * ```ts 72680 * ɵɵstylePropInterpolate5(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix'); 72681 * ``` 72682 * 72683 * @param styleIndex Index of style to update. This index value refers to the 72684 * index of the style in the style bindings array that was passed into 72685 * `styling`. 72686 * @param prefix Static value used for concatenation only. 72687 * @param v0 Value checked for change. 72688 * @param i0 Static value used for concatenation only. 72689 * @param v1 Value checked for change. 72690 * @param i1 Static value used for concatenation only. 72691 * @param v2 Value checked for change. 72692 * @param i2 Static value used for concatenation only. 72693 * @param v3 Value checked for change. 72694 * @param i3 Static value used for concatenation only. 72695 * @param v4 Value checked for change. 72696 * @param suffix Static value used for concatenation only. 72697 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`. 72698 * @returns itself, so that it may be chained. 72699 * @codeGenApi 72700 */ 72701 72702 72703function ɵɵstylePropInterpolate5(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix, valueSuffix) { 72704 const lView = getLView(); 72705 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix); 72706 checkStylingProperty(prop, interpolatedValue, valueSuffix, false); 72707 return ɵɵstylePropInterpolate5; 72708} 72709/** 72710 * 72711 * Update an interpolated style property on an element with 6 bound values surrounded by text. 72712 * 72713 * Used when the value passed to a property has 6 interpolated values in it: 72714 * 72715 * ```html 72716 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div> 72717 * ``` 72718 * 72719 * Its compiled representation is: 72720 * 72721 * ```ts 72722 * ɵɵstylePropInterpolate6(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix'); 72723 * ``` 72724 * 72725 * @param styleIndex Index of style to update. This index value refers to the 72726 * index of the style in the style bindings array that was passed into 72727 * `styling`. 72728 * @param prefix Static value used for concatenation only. 72729 * @param v0 Value checked for change. 72730 * @param i0 Static value used for concatenation only. 72731 * @param v1 Value checked for change. 72732 * @param i1 Static value used for concatenation only. 72733 * @param v2 Value checked for change. 72734 * @param i2 Static value used for concatenation only. 72735 * @param v3 Value checked for change. 72736 * @param i3 Static value used for concatenation only. 72737 * @param v4 Value checked for change. 72738 * @param i4 Static value used for concatenation only. 72739 * @param v5 Value checked for change. 72740 * @param suffix Static value used for concatenation only. 72741 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`. 72742 * @returns itself, so that it may be chained. 72743 * @codeGenApi 72744 */ 72745 72746 72747function ɵɵstylePropInterpolate6(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix, valueSuffix) { 72748 const lView = getLView(); 72749 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix); 72750 checkStylingProperty(prop, interpolatedValue, valueSuffix, false); 72751 return ɵɵstylePropInterpolate6; 72752} 72753/** 72754 * 72755 * Update an interpolated style property on an element with 7 bound values surrounded by text. 72756 * 72757 * Used when the value passed to a property has 7 interpolated values in it: 72758 * 72759 * ```html 72760 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div> 72761 * ``` 72762 * 72763 * Its compiled representation is: 72764 * 72765 * ```ts 72766 * ɵɵstylePropInterpolate7( 72767 * 0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix'); 72768 * ``` 72769 * 72770 * @param styleIndex Index of style to update. This index value refers to the 72771 * index of the style in the style bindings array that was passed into 72772 * `styling`.
72773 * @param prefix Static value used for concatenation only. 72774 * @param v0 Value checked for change. 72775 * @param i0 Static value used for concatenation only. 72776 * @param v1 Value checked for change. 72777 * @param i1 Static value used for concatenation only. 72778 * @param v2 Value checked for change. 72779 * @param i2 Static value used for concatenation only. 72780 * @param v3 Value checked for change. 72781 * @param i3 Static value used for concatenation only. 72782 * @param v4 Value checked for change. 72783 * @param i4 Static value used for concatenation only. 72784 * @param v5 Value checked for change. 72785 * @param i5 Static value used for concatenation only. 72786 * @param v6 Value checked for change. 72787 * @param suffix Static value used for concatenation only. 72788 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`. 72789 * @returns itself, so that it may be chained. 72790 * @codeGenApi 72791 */ 72792 72793 72794function ɵɵstylePropInterpolate7(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix, valueSuffix) { 72795 const lView = getLView(); 72796 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix); 72797 checkStylingProperty(prop, interpolatedValue, valueSuffix, false); 72798 return ɵɵstylePropInterpolate7; 72799} 72800/** 72801 * 72802 * Update an interpolated style property on an element with 8 bound values surrounded by text. 72803 * 72804 * Used when the value passed to a property has 8 interpolated values in it: 72805 * 72806 * ```html 72807 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div> 72808 * ``` 72809 * 72810 * Its compiled representation is: 72811 * 72812 * ```ts 72813 * ɵɵstylePropInterpolate8(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 72814 * '-', v7, 'suffix'); 72815 * ``` 72816 * 72817 * @param styleIndex Index of style to update. This index value refers to the 72818 * index of the style in the style bindings array that was passed into 72819 * `styling`. 72820 * @param prefix Static value used for concatenation only. 72821 * @param v0 Value checked for change. 72822 * @param i0 Static value used for concatenation only. 72823 * @param v1 Value checked for change. 72824 * @param i1 Static value used for concatenation only. 72825 * @param v2 Value checked for change. 72826 * @param i2 Static value used for concatenation only. 72827 * @param v3 Value checked for change. 72828 * @param i3 Static value used for concatenation only. 72829 * @param v4 Value checked for change. 72830 * @param i4 Static value used for concatenation only. 72831 * @param v5 Value checked for change. 72832 * @param i5 Static value used for concatenation only. 72833 * @param v6 Value checked for change. 72834 * @param i6 Static value used for concatenation only. 72835 * @param v7 Value checked for change. 72836 * @param suffix Static value used for concatenation only. 72837 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`. 72838 * @returns itself, so that it may be chained. 72839 * @codeGenApi 72840 */ 72841 72842 72843function ɵɵstylePropInterpolate8(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix, valueSuffix) { 72844 const lView = getLView(); 72845 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix); 72846 checkStylingProperty(prop, interpolatedValue, valueSuffix, false); 72847 return ɵɵstylePropInterpolate8; 72848} 72849/** 72850 * Update an interpolated style property on an element with 9 or more bound values surrounded by 72851 * text. 72852 * 72853 * Used when the number of interpolated values exceeds 8. 72854 * 72855 * ```html 72856 * <div 72857 * style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"> 72858 * </div> 72859 * ``` 72860 * 72861 * Its compiled representation is: 72862 * 72863 * ```ts 72864 * ɵɵstylePropInterpolateV( 72865 * 0, ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9, 72866 * 'suffix']); 72867 * ``` 72868 * 72869 * @param styleIndex Index of style to update. This index value refers to the 72870 * index of the style in the style bindings array that was passed into 72871 * `styling`.. 72872 * @param values The collection of values and the strings in-between those values, beginning with 72873 * a string prefix and ending with a string suffix. 72874 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`) 72875 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`. 72876 * @returns itself, so that it may be chained. 72877 * @codeGenApi 72878 */ 72879 72880
vendor: 5,148 bytes, lines 72881-73007
72881function ɵɵstylePropInterpolateV(prop, values, valueSuffix) { 72882 const lView = getLView(); 72883 const interpolatedValue = interpolationV(lView, values); 72884 checkStylingProperty(prop, interpolatedValue, valueSuffix, false); 72885 return ɵɵstylePropInterpolateV; 72886} 72887/** 72888 * @license 72889 * Copyright Google LLC All Rights Reserved. 72890 * 72891 * Use of this source code is governed by an MIT-style license that can be 72892 * found in the LICENSE file at https://angular.io/license 72893 */ 72894 72895/** 72896 * Update a property on a host element. Only applies to native node properties, not inputs. 72897 * 72898 * Operates on the element selected by index via the {@link select} instruction. 72899 * 72900 * @param propName Name of property. Because it is going to DOM, this is not subject to 72901 * renaming as part of minification. 72902 * @param value New value to write. 72903 * @param sanitizer An optional function used to sanitize the value. 72904 * @returns This function returns itself so that it may be chained 72905 * (e.g. `property('name', ctx.name)('title', ctx.title)`) 72906 * 72907 * @codeGenApi 72908 */ 72909 72910 72911function ɵɵhostProperty(propName, value, sanitizer) { 72912 const lView = getLView(); 72913 const bindingIndex = nextBindingIndex(); 72914 72915 if (bindingUpdated(lView, bindingIndex, value)) { 72916 const tView = getTView(); 72917 const tNode = getSelectedTNode(); 72918 elementPropertyInternal(tView, tNode, lView, propName, value, lView[RENDERER], sanitizer, true); 72919 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex); 72920 } 72921 72922 return ɵɵhostProperty; 72923} 72924/** 72925 * Updates a synthetic host binding (e.g. `[@foo]`) on a component or directive. 72926 * 72927 * This instruction is for compatibility purposes and is designed to ensure that a 72928 * synthetic host binding (e.g. `@HostBinding('@foo')`) properly gets rendered in 72929 * the component's renderer. Normally all host bindings are evaluated with the parent 72930 * component's renderer, but, in the case of animation @triggers, they need to be 72931 * evaluated with the sub component's renderer (because that's where the animation 72932 * triggers are defined). 72933 * 72934 * Do not use this instruction as a replacement for `elementProperty`. This instruction 72935 * only exists to ensure compatibility with the ViewEngine's host binding behavior. 72936 * 72937 * @param index The index of the element to update in the data array 72938 * @param propName Name of property. Because it is going to DOM, this is not subject to 72939 * renaming as part of minification. 72940 * @param value New value to write. 72941 * @param sanitizer An optional function used to sanitize the value. 72942 * 72943 * @codeGenApi 72944 */ 72945 72946 72947function ɵɵsyntheticHostProperty(propName, value, sanitizer) { 72948 const lView = getLView(); 72949 const bindingIndex = nextBindingIndex(); 72950 72951 if (bindingUpdated(lView, bindingIndex, value)) { 72952 const tView = getTView(); 72953 const tNode = getSelectedTNode(); 72954 const currentDef = getCurrentDirectiveDef(tView.data); 72955 const renderer = loadComponentRenderer(currentDef, tNode, lView); 72956 elementPropertyInternal(tView, tNode, lView, propName, value, renderer, sanitizer, true); 72957 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex); 72958 } 72959 72960 return ɵɵsyntheticHostProperty; 72961} 72962/** 72963 * @license 72964 * Copyright Google LLC All Rights Reserved. 72965 * 72966 * Use of this source code is governed by an MIT-style license that can be 72967 * found in the LICENSE file at https://angular.io/license 72968 */ 72969 72970/** 72971 * NOTE: changes to the `ngI18nClosureMode` name must be synced with `compiler-cli/src/tooling.ts`. 72972 */ 72973 72974 72975if (typeof ngI18nClosureMode === 'undefined') { 72976 // These property accesses can be ignored because ngI18nClosureMode will be set to false 72977 // when optimizing code and the whole if statement will be dropped. 72978 // Make sure to refer to ngI18nClosureMode as ['ngI18nClosureMode'] for closure. 72979 // NOTE: we need to have it in IIFE so that the tree-shaker is happy. 72980 (function () { 72981 // tslint:disable-next-line:no-toplevel-property-access 72982 _global['ngI18nClosureMode'] = // TODO(FW-1250): validate that this actually, you know, works. 72983 // tslint:disable-next-line:no-toplevel-property-access 72984 typeof goog !== 'undefined' && typeof goog.getMsg === 'function'; 72985 })(); 72986} 72987/** 72988 * @license 72989 * Copyright Google LLC All Rights Reserved. 72990 * 72991 * Use of this source code is governed by an MIT-style license that can be 72992 * found in the LICENSE file at https://angular.io/license 72993 */ 72994// THIS CODE IS GENERATED - DO NOT MODIFY. 72995 72996 72997const u = undefined; 72998 72999function plural(val) { 73000 const n = val, 73001 i = Math.floor(Math.abs(val)), 73002 v = val.toString().replace(/^[^.]*\.?/, '').length; 73003 if (i === 1 && v === 0) return 1; 73004 return 5; 73005} 73006 73007var localeEn = ["en", [["a", "p"], ["AM", "PM"], u], [["AM", "PM"], u, u], [["S", "M", "T", "W", "T", "F", "S"], ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]], u, [["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"], ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
73007November", "December"]], u, [["B", "A"], ["BC", "AD"], ["Before Christ", "Anno Domini"]], 0, [6, 0], ["M/d/yy", "MMM d, y", "MMMM d, y", "EEEE, MMMM d, y"], ["h:mm a", "h:mm:ss a", "h:mm:ss a z", "h:mm:ss a zzzz"], ["{1}, {0}", u, "{1} 'at' {0}", u], [".", ",", ";", "%", "+", "-", "E", "Ã", "â°", "â", "NaN", ":"], ["#,##0.###", "#,##0%", "¤#,##0.00", "#E0"], "USD", "$", "US Dollar", {}, "ltr", plural]; 73008/** 73009 * @license 73010 * Copyright Google LLC All Rights Reserved. 73011 * 73012 * Use of this source code is governed by an MIT-style license that can be 73013 * found in the LICENSE file at https://angular.io/license 73014 */ 73015 73016/** 73017 * This const is used to store the locale data registered with `registerLocaleData` 73018 */ 73019 73020let LOCALE_DATA = {}; 73021/** 73022 * Register locale data to be used internally by Angular. See the 73023 * ["I18n guide"](guide/i18n-common-format-data-locale) to know how to import additional locale 73024 * data. 73025 * 73026 * The signature `registerLocaleData(data: any, extraData?: any)` is deprecated since v5.1 73027 */ 73028 73029function registerLocaleData(data, localeId, extraData) { 73030 if (typeof localeId !== 'string') { 73031 extraData = localeId; 73032 localeId = data[LocaleDataIndex.LocaleId]; 73033 } 73034 73035 localeId = localeId.toLowerCase().replace(/_/g, '-'); 73036 LOCALE_DATA[localeId] = data; 73037 73038 if (extraData) { 73039 LOCALE_DATA[localeId][LocaleDataIndex.ExtraData] = extraData; 73040 } 73041} 73042/** 73043 * Finds the locale data for a given locale. 73044 * 73045 * @param locale The locale code. 73046 * @returns The locale data. 73047 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 73048 */ 73049 73050 73051function findLocaleData(locale) { 73052 const normalizedLocale = normalizeLocale(locale); 73053 let match = getLocaleData(normalizedLocale); 73054 73055 if (match) { 73056 return match; 73057 } // let's try to find a parent locale 73058 73059 73060 const parentLocale = normalizedLocale.split('-')[0]; 73061 match = getLocaleData(parentLocale); 73062 73063 if (match) { 73064 return match; 73065 } 73066 73067 if (parentLocale === 'en') { 73068 return localeEn; 73069 } 73070 73071 throw new RuntimeError(701 73072 /* RuntimeErrorCode.MISSING_LOCALE_DATA */ 73073 , ngDevMode && `Missing locale data for the locale "${locale}".`); 73074} 73075/** 73076 * Retrieves the default currency code for the given locale. 73077 * 73078 * The default is defined as the first currency which is still in use. 73079 * 73080 * @param locale The code of the locale whose currency code we want. 73081 * @returns The code of the default currency for the given locale. 73082 * 73083 */ 73084 73085 73086function getLocaleCurrencyCode(locale) { 73087 const data = findLocaleData(locale); 73088 return data[LocaleDataIndex.CurrencyCode] || null; 73089} 73090/** 73091 * Retrieves the plural function used by ICU expressions to determine the plural case to use 73092 * for a given locale. 73093 * @param locale A locale code for the locale format rules to use. 73094 * @returns The plural function for the locale. 73095 * @see `NgPlural` 73096 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview) 73097 */ 73098 73099 73100function getLocalePluralCase(locale) { 73101 const data = findLocaleData(locale); 73102 return data[LocaleDataIndex.PluralCase]; 73103} 73104/** 73105 * Helper function to get the given `normalizedLocale` from `LOCALE_DATA` 73106 * or from the global `ng.common.locale`. 73107 */ 73108 73109 73110function getLocaleData(normalizedLocale) { 73111 if (!(normalizedLocale in LOCALE_DATA)) { 73112 LOCALE_DATA[normalizedLocale] = _global.ng && _global.ng.common && _global.ng.common.locales && _global.ng.common.locales[normalizedLocale]; 73113 } 73114 73115 return LOCALE_DATA[normalizedLocale]; 73116} 73117/** 73118 * Helper function to remove all the locale data from `LOCALE_DATA`. 73119 */ 73120 73121 73122function unregisterAllLocaleData() { 73123 LOCALE_DATA = {}; 73124} 73125/** 73126 * Index of each type of locale data from the locale data array 73127 */ 73128 73129 73130var LocaleDataIndex; 73131 73132(function (LocaleDataIndex) { 73133 LocaleDataIndex[LocaleDataIndex["LocaleId"] = 0] = "LocaleId"; 73134 LocaleDataIndex[LocaleDataIndex["DayPeriodsFormat"] = 1] = "DayPeriodsFormat"; 73135 LocaleDataIndex[LocaleDataIndex["DayPeriodsStandalone"] = 2] = "DayPeriodsStandalone"; 73136 LocaleDataIndex[LocaleDataIndex["DaysFormat"] = 3] = "DaysFormat"; 73137 LocaleDataIndex[LocaleDataIndex["DaysStandalone"] = 4] = "DaysStandalone"; 73138 LocaleDataIndex[LocaleDataIndex["MonthsFormat"] = 5] = "MonthsFormat"; 73139 LocaleDataIndex[LocaleDataIndex["MonthsStandalone"] = 6] = "MonthsStandalone"; 73140 LocaleDataIndex[LocaleDataIndex["Eras"] = 7] = "Eras"; 73141 LocaleDataIndex[LocaleDataIndex["FirstDayOfWeek"] = 8] = "FirstDayOfWeek";
73142 LocaleDataIndex[LocaleDataIndex["WeekendRange"] = 9] = "WeekendRange"; 73143 LocaleDataIndex[LocaleDataIndex["DateFormat"] = 10] = "DateFormat"; 73144 LocaleDataIndex[LocaleDataIndex["TimeFormat"] = 11] = "TimeFormat"; 73145 LocaleDataIndex[LocaleDataIndex["DateTimeFormat"] = 12] = "DateTimeFormat"; 73146 LocaleDataIndex[LocaleDataIndex["NumberSymbols"] = 13] = "NumberSymbols"; 73147 LocaleDataIndex[LocaleDataIndex["NumberFormats"] = 14] = "NumberFormats"; 73148 LocaleDataIndex[LocaleDataIndex["CurrencyCode"] = 15] = "CurrencyCode"; 73149 LocaleDataIndex[LocaleDataIndex["CurrencySymbol"] = 16] = "CurrencySymbol"; 73150 LocaleDataIndex[LocaleDataIndex["CurrencyName"] = 17] = "CurrencyName"; 73151 LocaleDataIndex[LocaleDataIndex["Currencies"] = 18] = "Currencies"; 73152 LocaleDataIndex[LocaleDataIndex["Directionality"] = 19] = "Directionality"; 73153 LocaleDataIndex[LocaleDataIndex["PluralCase"] = 20] = "PluralCase"; 73154 LocaleDataIndex[LocaleDataIndex["ExtraData"] = 21] = "ExtraData"; 73155})(LocaleDataIndex || (LocaleDataIndex = {})); 73156/** 73157 * Returns the canonical form of a locale name - lowercase with `_` replaced with `-`. 73158 */ 73159 73160 73161function normalizeLocale(locale) { 73162 return locale.toLowerCase().replace(/_/g, '-'); 73163} 73164/** 73165 * @license 73166 * Copyright Google LLC All Rights Reserved. 73167 * 73168 * Use of this source code is governed by an MIT-style license that can be 73169 * found in the LICENSE file at https://angular.io/license 73170 */ 73171 73172 73173const pluralMapping = ['zero', 'one', 'two', 'few', 'many']; 73174/** 73175 * Returns the plural case based on the locale 73176 */ 73177 73178function getPluralCase(value, locale) { 73179 const plural = getLocalePluralCase(locale)(parseInt(value, 10)); 73180 const result = pluralMapping[plural]; 73181 return result !== undefined ? result : 'other'; 73182} 73183/** 73184 * The locale id that the application is using by default (for translations and ICU expressions). 73185 */ 73186 73187 73188const DEFAULT_LOCALE_ID = 'en-US'; 73189/** 73190 * USD currency code that the application uses by default for CurrencyPipe when no 73191 * DEFAULT_CURRENCY_CODE is provided. 73192 */ 73193 73194const USD_CURRENCY_CODE = 'USD'; 73195/** 73196 * @license 73197 * Copyright Google LLC All Rights Reserved. 73198 * 73199 * Use of this source code is governed by an MIT-style license that can be 73200 * found in the LICENSE file at https://angular.io/license 73201 */ 73202 73203/** 73204 * Marks that the next string is an element name. 73205 * 73206 * See `I18nMutateOpCodes` documentation. 73207 */ 73208 73209const ELEMENT_MARKER = { 73210 marker: 'element' 73211}; 73212/** 73213 * Marks that the next string is comment text need for ICU. 73214 * 73215 * See `I18nMutateOpCodes` documentation. 73216 */ 73217 73218const ICU_MARKER = { 73219 marker: 'ICU' 73220}; 73221/** 73222 * See `I18nCreateOpCodes` 73223 */ 73224 73225var I18nCreateOpCode; 73226 73227(function (I18nCreateOpCode) { 73228 /** 73229 * Number of bits to shift index so that it can be combined with the `APPEND_EAGERLY` and 73230 * `COMMENT`. 73231 */ 73232 I18nCreateOpCode[I18nCreateOpCode["SHIFT"] = 2] = "SHIFT"; 73233 /** 73234 * Should the node be appended to parent immediately after creation. 73235 */ 73236 73237 I18nCreateOpCode[I18nCreateOpCode["APPEND_EAGERLY"] = 1] = "APPEND_EAGERLY"; 73238 /** 73239 * If set the node should be comment (rather than a text) node. 73240 */ 73241 73242 I18nCreateOpCode[I18nCreateOpCode["COMMENT"] = 2] = "COMMENT"; 73243})(I18nCreateOpCode || (I18nCreateOpCode = {})); // Note: This hack is necessary so we don't erroneously get a circular dependency 73244// failure based on types. 73245 73246 73247const unusedValueExportToPlacateAjd$2 = 1; 73248/** 73249 * @license 73250 * Copyright Google LLC All Rights Reserved. 73251 * 73252 * Use of this source code is governed by an MIT-style license that can be 73253 * found in the LICENSE file at https://angular.io/license 73254 */ 73255 73256/** 73257 * The locale id that the application is currently using (for translations and ICU expressions). 73258 * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine 73259 * but is now defined as a global value. 73260 */ 73261 73262let LOCALE_ID$1 = DEFAULT_LOCALE_ID; 73263/** 73264 * Sets the locale id that will be used for translations and ICU expressions. 73265 * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine 73266 * but is now defined as a global value. 73267 * 73268 * @param localeId 73269 */ 73270 73271function setLocaleId(localeId) { 73272 assertDefined(localeId, `Expected localeId to be defined`); 73273 73274 if (typeof localeId === 'string') { 73275 LOCALE_ID$1 = localeId.toLowerCase().replace(/_/g, '-'); 73276 } 73277} 73278/** 73279 * Gets the locale id that will be used for translations and ICU expressions. 73280 * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine 73281 * but is now defined as a global value. 73282 */ 73283 73284 73285function getLocaleId() { 73286 return LOCALE_ID$1; 73287} 73288/** 73289 * @license 73290 * Copyright Google LLC All Rights Reserved. 73291 * 73292 * Use of this source code is governed by an MIT-style license that can be 73293 * found in the LICENSE file at https://angular.io/license 73294 */ 73295 73296/** 73297 * Find a node in front of which `currentTNode` should be inserted (takes i18n into account). 73298 * 73299 * This method determines the `RNode` in front of which we should insert the `currentRNode`. This 73300 * takes `TNode.insertBeforeIndex` into account. 73301 * 73302 * @param parentTNode parent `TNode` 73303 * @param currentTNode current `TNode` (The node which we would like to insert into the DOM) 73304 * @param lView current `LView` 73305 */ 73306 73307 73308function getInsertInFrontOfRNodeWithI18n(parentTNode, currentTNode, lView) { 73309 const tNodeInsertBeforeIndex = currentTNode.insertBeforeIndex; 73310 const insertBeforeIndex = Array.isArray(tNodeInsertBeforeIndex) ? tNodeInsertBeforeIndex[0] : tN
vendor: 5,669 bytes, lines 73310-73459
73310odeInsertBeforeIndex; 73311 73312 if (insertBeforeIndex === null) { 73313 return getInsertInFrontOfRNodeWithNoI18n(parentTNode, currentTNode, lView); 73314 } else { 73315 ngDevMode && assertIndexInRange(lView, insertBeforeIndex); 73316 return unwrapRNode(lView[insertBeforeIndex]); 73317 } 73318} 73319/** 73320 * Process `TNode.insertBeforeIndex` by adding i18n text nodes. 73321 * 73322 * See `TNode.insertBeforeIndex` 73323 */ 73324 73325 73326function processI18nInsertBefore(renderer, childTNode, lView, childRNode, parentRElement) { 73327 const tNodeInsertBeforeIndex = childTNode.insertBeforeIndex; 73328 73329 if (Array.isArray(tNodeInsertBeforeIndex)) { 73330 // An array indicates that there are i18n nodes that need to be added as children of this 73331 // `childRNode`. These i18n nodes were created before this `childRNode` was available and so 73332 // only now can be added. The first element of the array is the normal index where we should 73333 // insert the `childRNode`. Additional elements are the extra nodes to be added as children of 73334 // `childRNode`. 73335 ngDevMode && assertDomNode(childRNode); 73336 let i18nParent = childRNode; 73337 let anchorRNode = null; 73338 73339 if (!(childTNode.type & 3 73340 /* TNodeType.AnyRNode */ 73341 )) { 73342 anchorRNode = i18nParent; 73343 i18nParent = parentRElement; 73344 } 73345 73346 if (i18nParent !== null && (childTNode.flags & 2 73347 /* TNodeFlags.isComponentHost */ 73348 ) === 0) { 73349 for (let i = 1; i < tNodeInsertBeforeIndex.length; i++) { 73350 // No need to `unwrapRNode` because all of the indexes point to i18n text nodes. 73351 // see `assertDomNode` below. 73352 const i18nChild = lView[tNodeInsertBeforeIndex[i]]; 73353 nativeInsertBefore(renderer, i18nParent, i18nChild, anchorRNode, false); 73354 } 73355 } 73356 } 73357} 73358/** 73359 * @license 73360 * Copyright Google LLC All Rights Reserved. 73361 * 73362 * Use of this source code is governed by an MIT-style license that can be 73363 * found in the LICENSE file at https://angular.io/license 73364 */ 73365 73366/** 73367 * Add `tNode` to `previousTNodes` list and update relevant `TNode`s in `previousTNodes` list 73368 * `tNode.insertBeforeIndex`. 73369 * 73370 * Things to keep in mind: 73371 * 1. All i18n text nodes are encoded as `TNodeType.Element` and are created eagerly by the 73372 * `ɵɵi18nStart` instruction. 73373 * 2. All `TNodeType.Placeholder` `TNodes` are elements which will be created later by 73374 * `ɵɵelementStart` instruction. 73375 * 3. `ɵɵelementStart` instruction will create `TNode`s in the ascending `TNode.index` order. (So a 73376 * smaller index `TNode` is guaranteed to be created before a larger one) 73377 * 73378 * We use the above three invariants to determine `TNode.insertBeforeIndex`. 73379 * 73380 * In an ideal world `TNode.insertBeforeIndex` would always be `TNode.next.index`. However, 73381 * this will not work because `TNode.next.index` may be larger than `TNode.index` which means that 73382 * the next node is not yet created and therefore we can't insert in front of it. 73383 * 73384 * Rule1: `TNode.insertBeforeIndex = null` if `TNode.next === null` (Initial condition, as we don't 73385 * know if there will be further `TNode`s inserted after.) 73386 * Rule2: If `previousTNode` is created after the `tNode` being inserted, then 73387 * `previousTNode.insertBeforeNode = tNode.index` (So when a new `tNode` is added we check 73388 * previous to see if we can update its `insertBeforeTNode`) 73389 * 73390 * See `TNode.insertBeforeIndex` for more context. 73391 * 73392 * @param previousTNodes A list of previous TNodes so that we can easily traverse `TNode`s in 73393 * reverse order. (If `TNode` would have `previous` this would not be necessary.) 73394 * @param newTNode A TNode to add to the `previousTNodes` list. 73395 */ 73396 73397 73398function addTNodeAndUpdateInsertBeforeIndex(previousTNodes, newTNode) { 73399 // Start with Rule1 73400 ngDevMode && assertEqual(newTNode.insertBeforeIndex, null, 'We expect that insertBeforeIndex is not set'); 73401 previousTNodes.push(newTNode); 73402 73403 if (previousTNodes.length > 1) { 73404 for (let i = previousTNodes.length - 2; i >= 0; i--) { 73405 const existingTNode = previousTNodes[i]; // Text nodes are created eagerly and so they don't need their `indexBeforeIndex` updated. 73406 // It is safe to ignore them. 73407 73408 if (!isI18nText(existingTNode)) { 73409 if (isNewTNodeCreatedBefore(existingTNode, newTNode) && getInsertBeforeIndex(existingTNode) === null) { 73410 // If it was created before us in time, (and it does not yet have `insertBeforeIndex`) 73411 // then add the `insertBeforeIndex`. 73412 setInsertBeforeIndex(existingTNode, newTNode.index); 73413 } 73414 } 73415 } 73416 } 73417} 73418 73419function isI18nText(tNode) { 73420 return !(tNode.type & 64 73421 /* TNodeType.Placeholder */ 73422 ); 73423} 73424 73425function isNewTNodeCreatedBefore(existingTNode, newTNode) { 73426 return isI18nText(newTNode) || existingTNode.index > newTNode.index; 73427} 73428 73429function getInsertBeforeIndex(tNode) { 73430 const index = tNode.insertBeforeIndex; 73431 return Array.isArray(index) ? index[0] : index; 73432} 73433 73434function setInsertBeforeIndex(tNode, value) { 73435 const index = tNode.insertBeforeIndex; 73436 73437 if (Array.isArray(index)) { 73438 // Array is stored if we have to insert child nodes. See `TNode.insertBeforeIndex` 73439 index[0] = value; 73440 } else { 73441 setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore); 73442 tNode.insertBeforeIndex = value; 73443 } 73444} 73445/** 73446 * @license 73447 * Copyright Google LLC All Rights Reserved. 73448 * 73449 * Use of this source code is governed by an MIT-style license that can be 73450 * found in the LICENSE file at https://angular.io/license 73451 */ 73452 73453/** 73454 * Retrieve `TIcu` at a given `index`. 73455 * 73456 * The `TIcu` can be stored either directly (if it is nested ICU) OR 73457 * it is stored inside tho `TIcuContainer` if it is top level ICU. 73458 * 73459 * The reason for this is that the top level ICU need a `TNode` so that they are part of the render
73460 * tree, but nested ICU's have no TNode, because we don't know ahead of time if the nested ICU is 73461 * expressed (parent ICU may have selected a case which does not contain it.) 73462 * 73463 * @param tView Current `TView`. 73464 * @param index Index where the value should be read from. 73465 */ 73466 73467 73468function getTIcu(tView, index) { 73469 const value = tView.data[index]; 73470 if (value === null || typeof value === 'string') return null; 73471 73472 if (ngDevMode && !(value.hasOwnProperty('tViews') || value.hasOwnProperty('currentCaseLViewIndex'))) { 73473 throwError('We expect to get \'null\'|\'TIcu\'|\'TIcuContainer\', but got: ' + value); 73474 } // Here the `value.hasOwnProperty('currentCaseLViewIndex')` is a polymorphic read as it can be 73475 // either TIcu or TIcuContainerNode. This is not ideal, but we still think it is OK because it 73476 // will be just two cases which fits into the browser inline cache (inline cache can take up to 73477 // 4) 73478 73479 73480 const tIcu = value.hasOwnProperty('currentCaseLViewIndex') ? value : value.value; 73481 ngDevMode && assertTIcu(tIcu); 73482 return tIcu; 73483} 73484/** 73485 * Store `TIcu` at a give `index`. 73486 * 73487 * The `TIcu` can be stored either directly (if it is nested ICU) OR 73488 * it is stored inside tho `TIcuContainer` if it is top level ICU. 73489 * 73490 * The reason for this is that the top level ICU need a `TNode` so that they are part of the render
vendor: 84,070 bytes, lines 73491-75898
73491 * tree, but nested ICU's have no TNode, because we don't know ahead of time if the nested ICU is 73492 * expressed (parent ICU may have selected a case which does not contain it.) 73493 * 73494 * @param tView Current `TView`. 73495 * @param index Index where the value should be stored at in `Tview.data` 73496 * @param tIcu The TIcu to store. 73497 */ 73498 73499 73500function setTIcu(tView, index, tIcu) { 73501 const tNode = tView.data[index]; 73502 ngDevMode && assertEqual(tNode === null || tNode.hasOwnProperty('tViews'), true, 'We expect to get \'null\'|\'TIcuContainer\''); 73503 73504 if (tNode === null) { 73505 tView.data[index] = tIcu; 73506 } else { 73507 ngDevMode && assertTNodeType(tNode, 32 73508 /* TNodeType.Icu */ 73509 ); 73510 tNode.value = tIcu; 73511 } 73512} 73513/** 73514 * Set `TNode.insertBeforeIndex` taking the `Array` into account. 73515 * 73516 * See `TNode.insertBeforeIndex` 73517 */ 73518 73519 73520function setTNodeInsertBeforeIndex(tNode, index) { 73521 ngDevMode && assertTNode(tNode); 73522 let insertBeforeIndex = tNode.insertBeforeIndex; 73523 73524 if (insertBeforeIndex === null) { 73525 setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore); 73526 insertBeforeIndex = tNode.insertBeforeIndex = [null 73527 /* may be updated to number later */ 73528 , index]; 73529 } else { 73530 assertEqual(Array.isArray(insertBeforeIndex), true, 'Expecting array here'); 73531 insertBeforeIndex.push(index); 73532 } 73533} 73534/** 73535 * Create `TNode.type=TNodeType.Placeholder` node. 73536 * 73537 * See `TNodeType.Placeholder` for more information. 73538 */ 73539 73540 73541function createTNodePlaceholder(tView, previousTNodes, index) { 73542 const tNode = createTNodeAtIndex(tView, index, 64 73543 /* TNodeType.Placeholder */ 73544 , null, null); 73545 addTNodeAndUpdateInsertBeforeIndex(previousTNodes, tNode); 73546 return tNode; 73547} 73548/** 73549 * Returns current ICU case. 73550 * 73551 * ICU cases are stored as index into the `TIcu.cases`. 73552 * At times it is necessary to communicate that the ICU case just switched and that next ICU update 73553 * should update all bindings regardless of the mask. In such a case the we store negative numbers 73554 * for cases which have just been switched. This function removes the negative flag. 73555 */ 73556 73557 73558function getCurrentICUCaseIndex(tIcu, lView) { 73559 const currentCase = lView[tIcu.currentCaseLViewIndex]; 73560 return currentCase === null ? currentCase : currentCase < 0 ? ~currentCase : currentCase; 73561} 73562 73563function getParentFromIcuCreateOpCode(mergedCode) { 73564 return mergedCode >>> 17 73565 /* IcuCreateOpCode.SHIFT_PARENT */ 73566 ; 73567} 73568 73569function getRefFromIcuCreateOpCode(mergedCode) { 73570 return (mergedCode & 131070 73571 /* IcuCreateOpCode.MASK_REF */ 73572 ) >>> 1 73573 /* IcuCreateOpCode.SHIFT_REF */ 73574 ; 73575} 73576 73577function getInstructionFromIcuCreateOpCode(mergedCode) { 73578 return mergedCode & 1 73579 /* IcuCreateOpCode.MASK_INSTRUCTION */ 73580 ; 73581} 73582 73583function icuCreateOpCode(opCode, parentIdx, refIdx) { 73584 ngDevMode && assertGreaterThanOrEqual(parentIdx, 0, 'Missing parent index'); 73585 ngDevMode && assertGreaterThan(refIdx, 0, 'Missing ref index'); 73586 return opCode | parentIdx << 17 73587 /* IcuCreateOpCode.SHIFT_PARENT */ 73588 | refIdx << 1 73589 /* IcuCreateOpCode.SHIFT_REF */ 73590 ; 73591} 73592/** 73593 * @license 73594 * Copyright Google LLC All Rights Reserved. 73595 * 73596 * Use of this source code is governed by an MIT-style license that can be 73597 * found in the LICENSE file at https://angular.io/license 73598 */ 73599 73600/** 73601 * Keep track of which input bindings in `ɵɵi18nExp` have changed. 73602 * 73603 * This is used to efficiently update expressions in i18n only when the corresponding input has 73604 * changed. 73605 * 73606 * 1) Each bit represents which of the `ɵɵi18nExp` has changed. 73607 * 2) There are 32 bits allowed in JS. 73608 * 3) Bit 32 is special as it is shared for all changes past 32. (In other words if you have more 73609 * than 32 `ɵɵi18nExp` then all changes past 32nd `ɵɵi18nExp` will be mapped to same bit. This means 73610 * that we may end up changing more than we need to. But i18n expressions with 32 bindings is rare 73611 * so in practice it should not be an issue.) 73612 */ 73613 73614 73615let changeMask = 0b0; 73616/** 73617 * Keeps track of which bit needs to be updated in `changeMask` 73618 * 73619 * This value gets incremented on every call to `ɵɵi18nExp` 73620 */ 73621 73622let changeMaskCounter = 0; 73623/** 73624 * Keep track of which input bindings in `ɵɵi18nExp` have changed. 73625 * 73626 * `setMaskBit` gets invoked by each call to `ɵɵi18nExp`. 73627 * 73628 * @param hasChange did `ɵɵi18nExp` detect a change. 73629 */ 73630 73631function setMaskBit(hasChange) { 73632 if (hasChange) { 73633 changeMask = changeMask | 1 << Math.min(changeMaskCounter, 31); 73634 } 73635 73636 changeMaskCounter++; 73637} 73638 73639function applyI18n(tView, lView, index) { 73640 if (changeMaskCounter > 0) { 73641 ngDevMode && assertDefined(tView, `tView should be defined`); 73642 const tI18n = tView.data[index]; // When `index` points to an `ɵɵi18nAttributes` then we have an array otherwise `TI18n` 73643 73644 const updateOpCodes = Array.isArray(tI18n) ? tI18n : tI18n.update; 73645 const bindingsStartIndex = getBindingIndex() - changeMaskCounter - 1; 73646 applyUpdateOpCodes(tView, lView, updateOpCodes, bindingsStartIndex, changeMask); 73647 } // Reset changeMask & maskBit to default for the next update cycle 73648 73649 73650 changeMask = 0b0; 73651 changeMaskCounter = 0; 73652} 73653/** 73654 * Apply `I18nCreateOpCodes` op-codes as stored in `TI18n.create`. 73655 * 73656 * Creates text (and comment) nodes which are internationalized. 73657 * 73658 * @param lView Current lView 73659 * @param createOpCodes Set of op-codes to apply 73660 * @param parentRNode Parent node (so that direct children can be added eagerly) or `null` if it is 73661 * a root node. 73662 * @param insertInFrontOf DOM node that should be used as an anchor. 73663 */ 73664 73665 73666function applyCreateOpCodes(lView, createOpCodes, parentRNode, insertInFrontOf) { 73667 const renderer = lView[RENDERER]; 73668 73669 for (let i = 0; i < createOpCodes.length; i++) { 73670 const opCode = createOpCodes[i++]; 73671 const text = createOpCodes[i]; 73672 const isComment = (opCode & I18nCreateOpCode.COMMENT) === I18nCreateOpCode.COMMENT; 73673 const appendNow = (opCode & I18nCreateOpCode.APPEND_EAGERLY) === I18nCreateOpCode.APPEND_EAGERLY; 73674 const index = opCode >>> I18nCreateOpCode.SHIFT; 73675 let rNode = lView[index]; 73676 73677 if (rNode === null) { 73678 // We only create new DOM nodes if they don't already exist: If ICU switches case back to a 73679 // case which was already instantiated, no need to create new DOM nodes. 73680 rNode = lView[index] = isComment ? renderer.createComment(text) : createTextNode(renderer, text); 73681 } 73682 73683 if (appendNow && parentRNode !== null) { 73684 nativeInsertBefore(renderer, parentRNode, rNode, insertInFrontOf, false); 73685 } 73686 } 73687} 73688/** 73689 * Apply `I18nMutateOpCodes` OpCodes. 73690 * 73691 * @param tView Current `TView` 73692 * @param mutableOpCodes Mutable OpCodes to process 73693 * @param lView Current `LView` 73694 * @param anchorRNode place where the i18n node should be inserted. 73695 */ 73696 73697 73698function applyMutableOpCodes(tView, mutableOpCodes, lView, anchorRNode) { 73699 ngDevMode && assertDomNode(anchorRNode); 73700 const renderer = lView[RENDERER]; // `rootIdx` represents the node into which all inserts happen. 73701 73702 let rootIdx = null; // `rootRNode` represents the real node into which we insert. This can be different from 73703 // `lView[rootIdx]` if we have projection. 73704 // - null we don't have a parent (as can be the case in when we are inserting into a root of 73705 // LView which has no parent.) 73706 // - `RElement` The element representing the root after taking projection into account. 73707 73708 let rootRNode; 73709 73710 for (let i = 0; i < mutableOpCodes.length; i++) { 73711 const opCode = mutableOpCodes[i]; 73712 73713 if (typeof opCode == 'string') { 73714 const textNodeIndex = mutableOpCodes[++i]; 73715 73716 if (lView[textNodeIndex] === null) { 73717 ngDevMode && ngDevMode.rendererCreateTextNode++; 73718 ngDevMode && assertIndexInRange(lView, textNodeIndex); 73719 lView[textNodeIndex] = createTextNode(renderer, opCode); 73720 } 73721 } else if (typeof opCode == 'number') { 73722 switch (opCode & 1 73723 /* IcuCreateOpCode.MASK_INSTRUCTION */ 73724 ) { 73725 case 0 73726 /* IcuCreateOpCode.AppendChild */ 73727 : 73728 const parentIdx = getParentFromIcuCreateOpCode(opCode); 73729 73730 if (rootIdx === null) { 73731 // The first operation should save the `rootIdx` because the first operation 73732 // must insert into the root. (Only subsequent operations can insert into a dynamic 73733 // parent) 73734 rootIdx = parentIdx; 73735 rootRNode = nativeParentNode(renderer, anchorRNode); 73736 } 73737 73738 let insertInFrontOf; 73739 let parentRNode; 73740 73741 if (parentIdx === rootIdx) { 73742 insertInFrontOf = anchorRNode; 73743 parentRNode = rootRNode; 73744 } else { 73745 insertInFrontOf = null; 73746 parentRNode = unwrapRNode(lView[parentIdx]); 73747 } // FIXME(misko): Refactor with `processI18nText` 73748 73749 73750 if (parentRNode !== null) { 73751 // This can happen if the `LView` we are adding to is not attached to a parent `LView`. 73752 // In such a case there is no "root" we can attach to. This is fine, as we still need to 73753 // create the elements. When the `LView` gets later added to a parent these "root" nodes 73754 // get picked up and added. 73755 ngDevMode && assertDomNode(parentRNode); 73756 const refIdx = getRefFromIcuCreateOpCode(opCode); 73757 ngDevMode && assertGreaterThan(refIdx, HEADER_OFFSET, 'Missing ref'); // `unwrapRNode` is not needed here as all of these point to RNodes as part of the i18n 73758 // which can't have components. 73759 73760 const child = lView[refIdx]; 73761 ngDevMode && assertDomNode(child); 73762 nativeInsertBefore(renderer, parentRNode, child, insertInFrontOf, false); 73763 const tIcu = getTIcu(tView, refIdx); 73764 73765 if (tIcu !== null && typeof tIcu === 'object') { 73766 // If we just added a comment node which has ICU then that ICU may have already been 73767 // rendered and therefore we need to re-add it here. 73768 ngDevMode && assertTIcu(tIcu); 73769 const caseIndex = getCurrentICUCaseIndex(tIcu, lView); 73770 73771 if (caseIndex !== null) { 73772 applyMutableOpCodes(tView, tIcu.create[caseIndex], lView, lView[tIcu.anchorIdx]); 73773 } 73774 } 73775 } 73776 73777 break; 73778 73779 case 1 73780 /* IcuCreateOpCode.Attr */ 73781 : 73782 const elementNodeIndex = opCode >>> 1 73783 /* IcuCreateOpCode.SHIFT_REF */ 73784 ; 73785 const attrName = mutableOpCodes[++i]; 73786 const attrValue = mutableOpCodes[++i]; // This code is used for ICU expressions only, since we don't support 73787 // directives/components in ICUs, we don't need to worry about inputs here 73788 73789 setElementAttribute(renderer, getNativeByIndex(elementNodeIndex, lView), null, null, attrName, attrValue, null); 73790 break; 73791 73792 default: 73793 if (ngDevMode) { 73794 throw new RuntimeError(700 73795 /* RuntimeErrorCode.INVALID_I18N_STRUCTURE */ 73796 , `Unable to determine the type of mutate operation for "${opCode}"`); 73797 } 73798 73799 } 73800 } else { 73801 switch (opCode) { 73802 case ICU_MARKER: 73803 const commentValue = mutableOpCodes[++i]; 73804 const commentNodeIndex = mutableOpCodes[++i]; 73805 73806 if (lView[commentNodeIndex] === null) { 73807 ngDevMode && assertEqual(typeof commentValue, 'string', `Expected "${commentValue}" to be a comment node value`); 73808 ngDevMode && ngDevMode.rendererCreateComment++; 73809 ngDevMode && assertIndexInExpandoRange(lView, commentNodeIndex); 73810 const commentRNode = lView[commentNodeIndex] = createCommentNode(renderer, commentValue); // FIXME(misko): Attaching patch data is only needed for the root (Also add tests) 73811 73812 attachPatchData(commentRNode, lView); 73813 } 73814 73815 break; 73816 73817 case ELEMENT_MARKER: 73818 const tagName = mutableOpCodes[++i]; 73819 const elementNodeIndex = mutableOpCodes[++i]; 73820 73821 if (lView[elementNodeIndex] === null) { 73822 ngDevMode && assertEqual(typeof tagName, 'string', `Expected "${tagName}" to be an element node tag name`); 73823 ngDevMode && ngDevMode.rendererCreateElement++; 73824 ngDevMode && assertIndexInExpandoRange(lView, elementNodeIndex); 73825 const elementRNode = lView[elementNodeIndex] = createElementNode(renderer, tagName, null); // FIXME(misko): Attaching patch data is only needed for the root (Also add tests) 73826 73827 attachPatchData(elementRNode, lView); 73828 } 73829 73830 break; 73831 73832 default: 73833 ngDevMode && throwError(`Unable to determine the type of mutate operation for "${opCode}"`); 73834 } 73835 } 73836 } 73837} 73838/** 73839 * Apply `I18nUpdateOpCodes` OpCodes 73840 * 73841 * @param tView Current `TView` 73842 * @param lView Current `LView` 73843 * @param updateOpCodes OpCodes to process 73844 * @param bindingsStartIndex Location of the first `ɵɵi18nApply` 73845 * @param changeMask Each bit corresponds to a `ɵɵi18nExp` (Counting backwards from 73846 * `bindingsStartIndex`) 73847 */ 73848 73849 73850function applyUpdateOpCodes(tView, lView, updateOpCodes, bindingsStartIndex, changeMask) { 73851 for (let i = 0; i < updateOpCodes.length; i++) { 73852 // bit code to check if we should apply the next update 73853 const checkBit = updateOpCodes[i]; // Number of opCodes to skip until next set of update codes 73854 73855 const skipCodes = updateOpCodes[++i]; 73856 73857 if (checkBit & changeMask) { 73858 // The value has been updated since last checked 73859 let value = ''; 73860 73861 for (let j = i + 1; j <= i + skipCodes; j++) { 73862 const opCode = updateOpCodes[j]; 73863 73864 if (typeof opCode == 'string') { 73865 value += opCode; 73866 } else if (typeof opCode == 'number') { 73867 if (opCode < 0) { 73868 // Negative opCode represent `i18nExp` values offset. 73869 value += renderStringify(lView[bindingsStartIndex - opCode]); 73870 } else { 73871 const nodeIndex = opCode >>> 2 73872 /* I18nUpdateOpCode.SHIFT_REF */ 73873 ; 73874 73875 switch (opCode & 3 73876 /* I18nUpdateOpCode.MASK_OPCODE */ 73877 ) { 73878 case 1 73879 /* I18nUpdateOpCode.Attr */ 73880 : 73881 const propName = updateOpCodes[++j]; 73882 const sanitizeFn = updateOpCodes[++j]; 73883 const tNodeOrTagName = tView.data[nodeIndex]; 73884 ngDevMode && assertDefined(tNodeOrTagName, 'Experting TNode or string'); 73885 73886 if (typeof tNodeOrTagName === 'string') { 73887 // IF we don't have a `TNode`, then we are an element in ICU (as ICU content does 73888 // not have TNode), in which case we know that there are no directives, and hence 73889 // we use attribute setting. 73890 setElementAttribute(lView[RENDERER], lView[nodeIndex], null, tNodeOrTagName, propName, value, sanitizeFn); 73891 } else { 73892 elementPropertyInternal(tView, tNodeOrTagName, lView, propName, value, lView[RENDERER], sanitizeFn, false); 73893 } 73894 73895 break; 73896 73897 case 0 73898 /* I18nUpdateOpCode.Text */ 73899 : 73900 const rText = lView[nodeIndex]; 73901 rText !== null && updateTextNode(lView[RENDERER], rText, value); 73902 break; 73903 73904 case 2 73905 /* I18nUpdateOpCode.IcuSwitch */ 73906 : 73907 applyIcuSwitchCase(tView, getTIcu(tView, nodeIndex), lView, value); 73908 break; 73909 73910 case 3 73911 /* I18nUpdateOpCode.IcuUpdate */ 73912 : 73913 applyIcuUpdateCase(tView, getTIcu(tView, nodeIndex), bindingsStartIndex, lView); 73914 break; 73915 } 73916 } 73917 } 73918 } 73919 } else { 73920 const opCode = updateOpCodes[i + 1]; 73921 73922 if (opCode > 0 && (opCode & 3 73923 /* I18nUpdateOpCode.MASK_OPCODE */ 73924 ) === 3 73925 /* I18nUpdateOpCode.IcuUpdate */ 73926 ) { 73927 // Special case for the `icuUpdateCase`. It could be that the mask did not match, but 73928 // we still need to execute `icuUpdateCase` because the case has changed recently due to 73929 // previous `icuSwitchCase` instruction. (`icuSwitchCase` and `icuUpdateCase` always come in 73930 // pairs.) 73931 const nodeIndex = opCode >>> 2 73932 /* I18nUpdateOpCode.SHIFT_REF */ 73933 ; 73934 const tIcu = getTIcu(tView, nodeIndex); 73935 const currentIndex = lView[tIcu.currentCaseLViewIndex]; 73936 73937 if (currentIndex < 0) { 73938 applyIcuUpdateCase(tView, tIcu, bindingsStartIndex, lView); 73939 } 73940 } 73941 } 73942 73943 i += skipCodes; 73944 } 73945} 73946/** 73947 * Apply OpCodes associated with updating an existing ICU. 73948 * 73949 * @param tView Current `TView` 73950 * @param tIcu Current `TIcu` 73951 * @param bindingsStartIndex Location of the first `ɵɵi18nApply` 73952 * @param lView Current `LView` 73953 */ 73954 73955 73956function applyIcuUpdateCase(tView, tIcu, bindingsStartIndex, lView) { 73957 ngDevMode && assertIndexInRange(lView, tIcu.currentCaseLViewIndex); 73958 let activeCaseIndex = lView[tIcu.currentCaseLViewIndex]; 73959 73960 if (activeCaseIndex !== null) { 73961 let mask = changeMask; 73962 73963 if (activeCaseIndex < 0) { 73964 // Clear the flag. 73965 // Negative number means that the ICU was freshly created and we need to force the update. 73966 activeCaseIndex = lView[tIcu.currentCaseLViewIndex] = ~activeCaseIndex; // -1 is same as all bits on, which simulates creation since it marks all bits dirty 73967 73968 mask = -1; 73969 } 73970 73971 applyUpdateOpCodes(tView, lView, tIcu.update[activeCaseIndex], bindingsStartIndex, mask); 73972 } 73973} 73974/** 73975 * Apply OpCodes associated with switching a case on ICU. 73976 * 73977 * This involves tearing down existing case and than building up a new case. 73978 * 73979 * @param tView Current `TView` 73980 * @param tIcu Current `TIcu` 73981 * @param lView Current `LView` 73982 * @param value Value of the case to update to. 73983 */ 73984 73985 73986function applyIcuSwitchCase(tView, tIcu, lView, value) { 73987 // Rebuild a new case for this ICU 73988 const caseIndex = getCaseIndex(tIcu, value); 73989 let activeCaseIndex = getCurrentICUCaseIndex(tIcu, lView); 73990 73991 if (activeCaseIndex !== caseIndex) { 73992 applyIcuSwitchCaseRemove(tView, tIcu, lView); 73993 lView[tIcu.currentCaseLViewIndex] = caseIndex === null ? null : ~caseIndex; 73994 73995 if (caseIndex !== null) { 73996 // Add the nodes for the new case 73997 const anchorRNode = lView[tIcu.anchorIdx]; 73998 73999 if (anchorRNode) { 74000 ngDevMode && assertDomNode(anchorRNode); 74001 applyMutableOpCodes(tView, tIcu.create[caseIndex], lView, anchorRNode); 74002 } 74003 } 74004 } 74005} 74006/** 74007 * Apply OpCodes associated with tearing ICU case. 74008 * 74009 * This involves tearing down existing case and than building up a new case. 74010 * 74011 * @param tView Current `TView` 74012 * @param tIcu Current `TIcu` 74013 * @param lView Current `LView` 74014 */ 74015 74016 74017function applyIcuSwitchCaseRemove(tView, tIcu, lView) { 74018 let activeCaseIndex = getCurrentICUCaseIndex(tIcu, lView); 74019 74020 if (activeCaseIndex !== null) { 74021 const removeCodes = tIcu.remove[activeCaseIndex]; 74022 74023 for (let i = 0; i < removeCodes.length; i++) { 74024 const nodeOrIcuIndex = removeCodes[i]; 74025 74026 if (nodeOrIcuIndex > 0) { 74027 // Positive numbers are `RNode`s. 74028 const rNode = getNativeByIndex(nodeOrIcuIndex, lView); 74029 rNode !== null && nativeRemoveNode(lView[RENDERER], rNode); 74030 } else { 74031 // Negative numbers are ICUs 74032 applyIcuSwitchCaseRemove(tView, getTIcu(tView, ~nodeOrIcuIndex), lView); 74033 } 74034 } 74035 } 74036} 74037/** 74038 * Returns the index of the current case of an ICU expression depending on the main binding value 74039 * 74040 * @param icuExpression 74041 * @param bindingValue The value of the main binding used by this ICU expression 74042 */ 74043 74044 74045function getCaseIndex(icuExpression, bindingValue) { 74046 let index = icuExpression.cases.indexOf(bindingValue); 74047 74048 if (index === -1) { 74049 switch (icuExpression.type) { 74050 case 1 74051 /* IcuType.plural */ 74052 : 74053 { 74054 const resolvedCase = getPluralCase(bindingValue, getLocaleId()); 74055 index = icuExpression.cases.indexOf(resolvedCase); 74056 74057 if (index === -1 && resolvedCase !== 'other') { 74058 index = icuExpression.cases.indexOf('other'); 74059 } 74060 74061 break; 74062 } 74063 74064 case 0 74065 /* IcuType.select */ 74066 : 74067 { 74068 index = icuExpression.cases.indexOf('other'); 74069 break; 74070 } 74071 } 74072 } 74073 74074 return index === -1 ? null : index; 74075} 74076/** 74077 * @license 74078 * Copyright Google LLC All Rights Reserved. 74079 * 74080 * Use of this source code is governed by an MIT-style license that can be 74081 * found in the LICENSE file at https://angular.io/license 74082 */ 74083 74084 74085function loadIcuContainerVisitor() { 74086 const _stack = []; 74087 74088 let _index = -1; 74089 74090 let _lView; 74091 74092 let _removes; 74093 /** 74094 * Retrieves a set of root nodes from `TIcu.remove`. Used by `TNodeType.ICUContainer` 74095 * to determine which root belong to the ICU. 74096 * 74097 * Example of usage. 74098 * ``` 74099 * const nextRNode = icuContainerIteratorStart(tIcuContainerNode, lView); 74100 * let rNode: RNode|null; 74101 * while(rNode = nextRNode()) { 74102 * console.log(rNode); 74103 * } 74104 * ``` 74105 * 74106 * @param tIcuContainerNode Current `TIcuContainerNode` 74107 * @param lView `LView` where the `RNode`s should be looked up. 74108 */ 74109 74110 74111 function icuContainerIteratorStart(tIcuContainerNode, lView) { 74112 _lView = lView; 74113 74114 while (_stack.length) _stack.pop(); 74115 74116 ngDevMode && assertTNodeForLView(tIcuContainerNode, lView); 74117 enterIcu(tIcuContainerNode.value, lView); 74118 return icuContainerIteratorNext; 74119 } 74120 74121 function enterIcu(tIcu, lView) { 74122 _index = 0; 74123 const currentCase = getCurrentICUCaseIndex(tIcu, lView); 74124 74125 if (currentCase !== null) { 74126 ngDevMode && assertNumberInRange(currentCase, 0, tIcu.cases.length - 1); 74127 _removes = tIcu.remove[currentCase]; 74128 } else { 74129 _removes = EMPTY_ARRAY; 74130 } 74131 } 74132 74133 function icuContainerIteratorNext() { 74134 if (_index < _removes.length) { 74135 const removeOpCode = _removes[_index++]; 74136 ngDevMode && assertNumber(removeOpCode, 'Expecting OpCode number'); 74137 74138 if (removeOpCode > 0) { 74139 const rNode = _lView[removeOpCode]; 74140 ngDevMode && assertDomNode(rNode); 74141 return rNode; 74142 } else { 74143 _stack.push(_index, _removes); // ICUs are represented by negative indices 74144 74145 74146 const tIcuIndex = ~removeOpCode; 74147 const tIcu = _lView[TVIEW].data[tIcuIndex]; 74148 ngDevMode && assertTIcu(tIcu); 74149 enterIcu(tIcu, _lView); 74150 return icuContainerIteratorNext(); 74151 } 74152 } else { 74153 if (_stack.length === 0) { 74154 return null; 74155 } else { 74156 _removes = _stack.pop(); 74157 _index = _stack.pop(); 74158 return icuContainerIteratorNext(); 74159 } 74160 } 74161 } 74162 74163 return icuContainerIteratorStart; 74164} 74165/** 74166 * @license 74167 * Copyright Google LLC All Rights Reserved. 74168 * 74169 * Use of this source code is governed by an MIT-style license that can be 74170 * found in the LICENSE file at https://angular.io/license 74171 */ 74172 74173/** 74174 * Converts `I18nCreateOpCodes` array into a human readable format. 74175 * 74176 * This function is attached to the `I18nCreateOpCodes.debug` property if `ngDevMode` is enabled. 74177 * This function provides a human readable view of the opcodes. This is useful when debugging the 74178 * application as well as writing more readable tests. 74179 * 74180 * @param this `I18nCreateOpCodes` if attached as a method. 74181 * @param opcodes `I18nCreateOpCodes` if invoked as a function. 74182 */ 74183 74184 74185function i18nCreateOpCodesToString(opcodes) { 74186 const createOpCodes = opcodes || (Array.isArray(this) ? this : []); 74187 let lines = []; 74188 74189 for (let i = 0; i < createOpCodes.length; i++) { 74190 const opCode = createOpCodes[i++]; 74191 const text = createOpCodes[i]; 74192 const isComment = (opCode & I18nCreateOpCode.COMMENT) === I18nCreateOpCode.COMMENT; 74193 const appendNow = (opCode & I18nCreateOpCode.APPEND_EAGERLY) === I18nCreateOpCode.APPEND_EAGERLY; 74194 const index = opCode >>> I18nCreateOpCode.SHIFT; 74195 lines.push(`lView[${index}] = document.${isComment ? 'createComment' : 'createText'}(${JSON.stringify(text)});`); 74196 74197 if (appendNow) { 74198 lines.push(`parent.appendChild(lView[${index}]);`); 74199 } 74200 } 74201 74202 return lines; 74203} 74204/** 74205 * Converts `I18nUpdateOpCodes` array into a human readable format. 74206 * 74207 * This function is attached to the `I18nUpdateOpCodes.debug` property if `ngDevMode` is enabled. 74208 * This function provides a human readable view of the opcodes. This is useful when debugging the 74209 * application as well as writing more readable tests. 74210 * 74211 * @param this `I18nUpdateOpCodes` if attached as a method. 74212 * @param opcodes `I18nUpdateOpCodes` if invoked as a function. 74213 */ 74214 74215 74216function i18nUpdateOpCodesToString(opcodes) { 74217 const parser = new OpCodeParser(opcodes || (Array.isArray(this) ? this : [])); 74218 let lines = []; 74219 74220 function consumeOpCode(value) { 74221 const ref = value >>> 2 74222 /* I18nUpdateOpCode.SHIFT_REF */ 74223 ; 74224 const opCode = value & 3 74225 /* I18nUpdateOpCode.MASK_OPCODE */ 74226 ; 74227 74228 switch (opCode) { 74229 case 0 74230 /* I18nUpdateOpCode.Text */ 74231 : 74232 return `(lView[${ref}] as Text).textContent = $$$`; 74233 74234 case 1 74235 /* I18nUpdateOpCode.Attr */ 74236 : 74237 const attrName = parser.consumeString(); 74238 const sanitizationFn = parser.consumeFunction(); 74239 const value = sanitizationFn ? `(${sanitizationFn})($$$)` : '$$$'; 74240 return `(lView[${ref}] as Element).setAttribute('${attrName}', ${value})`; 74241 74242 case 2 74243 /* I18nUpdateOpCode.IcuSwitch */ 74244 : 74245 return `icuSwitchCase(${ref}, $$$)`; 74246 74247 case 3 74248 /* I18nUpdateOpCode.IcuUpdate */ 74249 : 74250 return `icuUpdateCase(${ref})`; 74251 } 74252 74253 throw new Error('unexpected OpCode'); 74254 } 74255 74256 while (parser.hasMore()) { 74257 let mask = parser.consumeNumber(); 74258 let size = parser.consumeNumber(); 74259 const end = parser.i + size; 74260 const statements = []; 74261 let statement = ''; 74262 74263 while (parser.i < end) { 74264 let value = parser.consumeNumberOrString(); 74265 74266 if (typeof value === 'string') { 74267 statement += value; 74268 } else if (value < 0) { 74269 // Negative numbers are ref indexes 74270 // Here `i` refers to current binding index. It is to signify that the value is relative, 74271 // rather than absolute. 74272 statement += '${lView[i' + value + ']}'; 74273 } else { 74274 // Positive numbers are operations. 74275 const opCodeText = consumeOpCode(value); 74276 statements.push(opCodeText.replace('$$$', '`' + statement + '`') + ';'); 74277 statement = ''; 74278 } 74279 } 74280 74281 lines.push(`if (mask & 0b${mask.toString(2)}) { ${statements.join(' ')} }`); 74282 } 74283 74284 return lines; 74285} 74286/** 74287 * Converts `I18nCreateOpCodes` array into a human readable format. 74288 * 74289 * This function is attached to the `I18nCreateOpCodes.debug` if `ngDevMode` is enabled. This 74290 * function provides a human readable view of the opcodes. This is useful when debugging the 74291 * application as well as writing more readable tests. 74292 * 74293 * @param this `I18nCreateOpCodes` if attached as a method. 74294 * @param opcodes `I18nCreateOpCodes` if invoked as a function. 74295 */ 74296 74297 74298function icuCreateOpCodesToString(opcodes) { 74299 const parser = new OpCodeParser(opcodes || (Array.isArray(this) ? this : [])); 74300 let lines = []; 74301 74302 function consumeOpCode(opCode) { 74303 const parent = getParentFromIcuCreateOpCode(opCode); 74304 const ref = getRefFromIcuCreateOpCode(opCode); 74305 74306 switch (getInstructionFromIcuCreateOpCode(opCode)) { 74307 case 0 74308 /* IcuCreateOpCode.AppendChild */ 74309 : 74310 return `(lView[${parent}] as Element).appendChild(lView[${lastRef}])`; 74311 74312 case 1 74313 /* IcuCreateOpCode.Attr */ 74314 : 74315 return `(lView[${ref}] as Element).setAttribute("${parser.consumeString()}", "${parser.consumeString()}")`; 74316 } 74317 74318 throw new Error('Unexpected OpCode: ' + getInstructionFromIcuCreateOpCode(opCode)); 74319 } 74320 74321 let lastRef = -1; 74322 74323 while (parser.hasMore()) { 74324 let value = parser.consumeNumberStringOrMarker(); 74325 74326 if (value === ICU_MARKER) { 74327 const text = parser.consumeString(); 74328 lastRef = parser.consumeNumber(); 74329 lines.push(`lView[${lastRef}] = document.createComment("${text}")`); 74330 } else if (value === ELEMENT_MARKER) { 74331 const text = parser.consumeString(); 74332 lastRef = parser.consumeNumber(); 74333 lines.push(`lView[${lastRef}] = document.createElement("${text}")`); 74334 } else if (typeof value === 'string') { 74335 lastRef = parser.consumeNumber(); 74336 lines.push(`lView[${lastRef}] = document.createTextNode("${value}")`); 74337 } else if (typeof value === 'number') { 74338 const line = consumeOpCode(value); 74339 line && lines.push(line); 74340 } else { 74341 throw new Error('Unexpected value'); 74342 } 74343 } 74344 74345 return lines; 74346} 74347/** 74348 * Converts `I18nRemoveOpCodes` array into a human readable format. 74349 * 74350 * This function is attached to the `I18nRemoveOpCodes.debug` if `ngDevMode` is enabled. This 74351 * function provides a human readable view of the opcodes. This is useful when debugging the 74352 * application as well as writing more readable tests. 74353 * 74354 * @param this `I18nRemoveOpCodes` if attached as a method. 74355 * @param opcodes `I18nRemoveOpCodes` if invoked as a function. 74356 */ 74357 74358 74359function i18nRemoveOpCodesToString(opcodes) { 74360 const removeCodes = opcodes || (Array.isArray(this) ? this : []); 74361 let lines = []; 74362 74363 for (let i = 0; i < removeCodes.length; i++) { 74364 const nodeOrIcuIndex = removeCodes[i]; 74365 74366 if (nodeOrIcuIndex > 0) { 74367 // Positive numbers are `RNode`s. 74368 lines.push(`remove(lView[${nodeOrIcuIndex}])`); 74369 } else { 74370 // Negative numbers are ICUs 74371 lines.push(`removeNestedICU(${~nodeOrIcuIndex})`); 74372 } 74373 } 74374 74375 return lines; 74376} 74377 74378class OpCodeParser { 74379 constructor(codes) { 74380 this.i = 0; 74381 this.codes = codes; 74382 } 74383 74384 hasMore() { 74385 return this.i < this.codes.length; 74386 } 74387 74388 consumeNumber() { 74389 let value = this.codes[this.i++]; 74390 assertNumber(value, 'expecting number in OpCode'); 74391 return value; 74392 } 74393 74394 consumeString() { 74395 let value = this.codes[this.i++]; 74396 assertString(value, 'expecting string in OpCode'); 74397 return value; 74398 } 74399 74400 consumeFunction() { 74401 let value = this.codes[this.i++]; 74402 74403 if (value === null || typeof value === 'function') { 74404 return value; 74405 } 74406 74407 throw new Error('expecting function in OpCode'); 74408 } 74409 74410 consumeNumberOrString() { 74411 let value = this.codes[this.i++]; 74412 74413 if (typeof value === 'string') { 74414 return value; 74415 } 74416 74417 assertNumber(value, 'expecting number or string in OpCode'); 74418 return value; 74419 } 74420 74421 consumeNumberStringOrMarker() { 74422 let value = this.codes[this.i++]; 74423 74424 if (typeof value === 'string' || typeof value === 'number' || value == ICU_MARKER || value == ELEMENT_MARKER) { 74425 return value; 74426 } 74427 74428 assertNumber(value, 'expecting number, string, ICU_MARKER or ELEMENT_MARKER in OpCode'); 74429 return value; 74430 } 74431 74432} 74433/** 74434 * @license 74435 * Copyright Google LLC All Rights Reserved. 74436 * 74437 * Use of this source code is governed by an MIT-style license that can be 74438 * found in the LICENSE file at https://angular.io/license 74439 */ 74440 74441 74442const BINDING_REGEXP = /�(\d+):?\d*�/gi; 74443const ICU_REGEXP = /({\s*�\d+:?\d*�\s*,\s*\S{6}\s*,[\s\S]*})/gi; 74444const NESTED_ICU = /�(\d+)�/; 74445const ICU_BLOCK_REGEXP = /^\s*(�\d+:?\d*�)\s*,\s*(select|plural)\s*,/; 74446const MARKER = `�`; 74447const SUBTEMPLATE_REGEXP = /�\/?\*(\d+:\d+)�/gi; 74448const PH_REGEXP = /�(\/?[#*]\d+):?\d*�/gi; 74449/** 74450 * Angular Dart introduced &ngsp; as a placeholder for non-removable space, see: 74451 * https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart#L25-L32 74452 * In Angular Dart &ngsp; is converted to the 0xE500 PUA (Private Use Areas) unicode character 74453 * and later on replaced by a space. We are re-implementing the same idea here, since translations 74454 * might contain this special character. 74455 */ 74456 74457const NGSP_UNICODE_REGEXP = /\uE500/g; 74458 74459function replaceNgsp(value) { 74460 return value.replace(NGSP_UNICODE_REGEXP, ' '); 74461} 74462/** 74463 * Create dynamic nodes from i18n translation block. 74464 * 74465 * - Text nodes are created synchronously 74466 * - TNodes are linked into tree lazily 74467 * 74468 * @param tView Current `TView` 74469 * @parentTNodeIndex index to the parent TNode of this i18n block 74470 * @param lView Current `LView` 74471 * @param index Index of `ɵɵi18nStart` instruction. 74472 * @param message Message to translate. 74473 * @param subTemplateIndex Index into the sub template of message translation. (ie in case of 74474 * `ngIf`) (-1 otherwise) 74475 */ 74476 74477 74478function i18nStartFirstCreatePass(tView, parentTNodeIndex, lView, index, message, subTemplateIndex) { 74479 const rootTNode = getCurrentParentTNode(); 74480 const createOpCodes = []; 74481 const updateOpCodes = []; 74482 const existingTNodeStack = [[]]; 74483 74484 if (ngDevMode) { 74485 attachDebugGetter(createOpCodes, i18nCreateOpCodesToString); 74486 attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString); 74487 } 74488 74489 message = getTranslationForTemplate(message, subTemplateIndex); 74490 const msgParts = replaceNgsp(message).split(PH_REGEXP); 74491 74492 for (let i = 0; i < msgParts.length; i++) { 74493 let value = msgParts[i]; 74494 74495 if ((i & 1) === 0) { 74496 // Even indexes are text (including bindings & ICU expressions) 74497 const parts = i18nParseTextIntoPartsAndICU(value); 74498 74499 for (let j = 0; j < parts.length; j++) { 74500 let part = parts[j]; 74501 74502 if ((j & 1) === 0) { 74503 // `j` is odd therefore `part` is string 74504 const text = part; 74505 ngDevMode && assertString(text, 'Parsed ICU part should be string'); 74506 74507 if (text !== '') { 74508 i18nStartFirstCreatePassProcessTextNode(tView, rootTNode, existingTNodeStack[0], createOpCodes, updateOpCodes, lView, text); 74509 } 74510 } else { 74511 // `j` is Even therefor `part` is an `ICUExpression` 74512 const icuExpression = part; // Verify that ICU expression has the right shape. Translations might contain invalid 74513 // constructions (while original messages were correct), so ICU parsing at runtime may 74514 // not succeed (thus `icuExpression` remains a string). 74515 // Note: we intentionally retain the error here by not using `ngDevMode`, because 74516 // the value can change based on the locale and users aren't guaranteed to hit 74517 // an invalid string while they're developing. 74518 74519 if (typeof icuExpression !== 'object') { 74520 throw new Error(`Unable to parse ICU expression in "${message}" message.`); 74521 } 74522 74523 const icuContainerTNode = createTNodeAndAddOpCode(tView, rootTNode, existingTNodeStack[0], lView, createOpCodes, ngDevMode ? `ICU ${index}:${icuExpression.mainBinding}` : '', true); 74524 const icuNodeIndex = icuContainerTNode.index; 74525 ngDevMode && assertGreaterThanOrEqual(icuNodeIndex, HEADER_OFFSET, 'Index must be in absolute LView offset'); 74526 icuStart(tView, lView, updateOpCodes, parentTNodeIndex, icuExpression, icuNodeIndex); 74527 } 74528 } 74529 } else { 74530 // Odd indexes are placeholders (elements and sub-templates) 74531 // At this point value is something like: '/#1:2' (originally coming from '�/#1:2�') 74532 const isClosing = value.charCodeAt(0) === 47 74533 /* CharCode.SLASH */ 74534 ; 74535 const type = value.charCodeAt(isClosing ? 1 : 0); 74536 ngDevMode && assertOneOf(type, 42 74537 /* CharCode.STAR */ 74538 , 35 74539 /* CharCode.HASH */ 74540 ); 74541 const index = HEADER_OFFSET + Number.parseInt(value.substring(isClosing ? 2 : 1)); 74542 74543 if (isClosing) { 74544 existingTNodeStack.shift(); 74545 setCurrentTNode(getCurrentParentTNode(), false); 74546 } else { 74547 const tNode = createTNodePlaceholder(tView, existingTNodeStack[0], index); 74548 existingTNodeStack.unshift([]); 74549 setCurrentTNode(tNode, true); 74550 } 74551 } 74552 } 74553 74554 tView.data[index] = { 74555 create: createOpCodes, 74556 update: updateOpCodes 74557 }; 74558} 74559/** 74560 * Allocate space in i18n Range add create OpCode instruction to create a text or comment node. 74561 * 74562 * @param tView Current `TView` needed to allocate space in i18n range. 74563 * @param rootTNode Root `TNode` of the i18n block. This node determines if the new TNode will be 74564 * added as part of the `i18nStart` instruction or as part of the `TNode.insertBeforeIndex`. 74565 * @param existingTNodes internal state for `addTNodeAndUpdateInsertBeforeIndex`. 74566 * @param lView Current `LView` needed to allocate space in i18n range. 74567 * @param createOpCodes Array storing `I18nCreateOpCodes` where new opCodes will be added. 74568 * @param text Text to be added when the `Text` or `Comment` node will be created. 74569 * @param isICU true if a `Comment` node for ICU (instead of `Text`) node should be created. 74570 */ 74571 74572 74573function createTNodeAndAddOpCode(tView, rootTNode, existingTNodes, lView, createOpCodes, text, isICU) { 74574 const i18nNodeIdx = allocExpando(tView, lView, 1, null); 74575 let opCode = i18nNodeIdx << I18nCreateOpCode.SHIFT; 74576 let parentTNode = getCurrentParentTNode(); 74577 74578 if (rootTNode === parentTNode) { 74579 // FIXME(misko): A null `parentTNode` should represent when we fall of the `LView` boundary. 74580 // (there is no parent), but in some circumstances (because we are inconsistent about how we set 74581 // `previousOrParentTNode`) it could point to `rootTNode` So this is a work around. 74582 parentTNode = null; 74583 } 74584 74585 if (parentTNode === null) { 74586 // If we don't have a parent that means that we can eagerly add nodes. 74587 // If we have a parent than these nodes can't be added now (as the parent has not been created 74588 // yet) and instead the `parentTNode` is responsible for adding it. See 74589 // `TNode.insertBeforeIndex` 74590 opCode |= I18nCreateOpCode.APPEND_EAGERLY; 74591 } 74592 74593 if (isICU) { 74594 opCode |= I18nCreateOpCode.COMMENT; 74595 ensureIcuContainerVisitorLoaded(loadIcuContainerVisitor); 74596 } 74597 74598 createOpCodes.push(opCode, text === null ? '' : text); // We store `{{?}}` so that when looking at debug `TNodeType.template` we can see where the 74599 // bindings are. 74600 74601 const tNode = createTNodeAtIndex(tView, i18nNodeIdx, isICU ? 32 74602 /* TNodeType.Icu */ 74603 : 1 74604 /* TNodeType.Text */ 74605 , text === null ? ngDevMode ? '{{?}}' : '' : text, null); 74606 addTNodeAndUpdateInsertBeforeIndex(existingTNodes, tNode); 74607 const tNodeIdx = tNode.index; 74608 setCurrentTNode(tNode, false 74609 /* Text nodes are self closing */ 74610 ); 74611 74612 if (parentTNode !== null && rootTNode !== parentTNode) { 74613 // We are a child of deeper node (rather than a direct child of `i18nStart` instruction.) 74614 // We have to make sure to add ourselves to the parent. 74615 setTNodeInsertBeforeIndex(parentTNode, tNodeIdx); 74616 } 74617 74618 return tNode; 74619} 74620/** 74621 * Processes text node in i18n block. 74622 * 74623 * Text nodes can have: 74624 * - Create instruction in `createOpCodes` for creating the text node. 74625 * - Allocate spec for text node in i18n range of `LView` 74626 * - If contains binding: 74627 * - bindings => allocate space in i18n range of `LView` to store the binding value. 74628 * - populate `updateOpCodes` with update instructions. 74629 * 74630 * @param tView Current `TView` 74631 * @param rootTNode Root `TNode` of the i18n block. This node determines if the new TNode will 74632 * be added as part of the `i18nStart` instruction or as part of the 74633 * `TNode.insertBeforeIndex`. 74634 * @param existingTNodes internal state for `addTNodeAndUpdateInsertBeforeIndex`. 74635 * @param createOpCodes Location where the creation OpCodes will be stored. 74636 * @param lView Current `LView` 74637 * @param text The translated text (which may contain binding) 74638 */ 74639 74640 74641function i18nStartFirstCreatePassProcessTextNode(tView, rootTNode, existingTNodes, createOpCodes, updateOpCodes, lView, text) { 74642 const hasBinding = text.match(BINDING_REGEXP); 74643 const tNode = createTNodeAndAddOpCode(tView, rootTNode, existingTNodes, lView, createOpCodes, hasBinding ? null : text, false); 74644 74645 if (hasBinding) { 74646 generateBindingUpdateOpCodes(updateOpCodes, text, tNode.index, null, 0, null); 74647 } 74648} 74649/** 74650 * See `i18nAttributes` above. 74651 */ 74652 74653 74654function i18nAttributesFirstPass(tView, index, values) { 74655 const previousElement = getCurrentTNode(); 74656 const previousElementIndex = previousElement.index; 74657 const updateOpCodes = []; 74658 74659 if (ngDevMode) { 74660 attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString); 74661 } 74662 74663 if (tView.firstCreatePass && tView.data[index] === null) { 74664 for (let i = 0; i < values.length; i += 2) { 74665 const attrName = values[i]; 74666 const message = values[i + 1]; 74667 74668 if (message !== '') { 74669 // Check if attribute value contains an ICU and throw an error if that's the case. 74670 // ICUs in element attributes are not supported. 74671 // Note: we intentionally retain the error here by not using `ngDevMode`, because 74672 // the `value` can change based on the locale and users aren't guaranteed to hit 74673 // an invalid string while they're developing. 74674 if (ICU_REGEXP.test(message)) { 74675 throw new Error(`ICU expressions are not supported in attributes. Message: "${message}".`); 74676 } // i18n attributes that hit this code path are guaranteed to have bindings, because 74677 // the compiler treats static i18n attributes as regular attribute bindings. 74678 // Since this may not be the first i18n attribute on this element we need to pass in how 74679 // many previous bindings there have already been. 74680 74681 74682 generateBindingUpdateOpCodes(updateOpCodes, message, previousElementIndex, attrName, countBindings(updateOpCodes), null); 74683 } 74684 } 74685 74686 tView.data[index] = updateOpCodes; 74687 } 74688} 74689/** 74690 * Generate the OpCodes to update the bindings of a string. 74691 * 74692 * @param updateOpCodes Place where the update opcodes will be stored. 74693 * @param str The string containing the bindings. 74694 * @param destinationNode Index of the destination node which will receive the binding. 74695 * @param attrName Name of the attribute, if the string belongs to an attribute. 74696 * @param sanitizeFn Sanitization function used to sanitize the string after update, if necessary. 74697 * @param bindingStart The lView index of the next expression that can be bound via an opCode. 74698 * @returns The mask value for these bindings 74699 */ 74700 74701 74702function generateBindingUpdateOpCodes(updateOpCodes, str, destinationNode, attrName, bindingStart, sanitizeFn) { 74703 ngDevMode && assertGreaterThanOrEqual(destinationNode, HEADER_OFFSET, 'Index must be in absolute LView offset'); 74704 const maskIndex = updateOpCodes.length; // Location of mask 74705 74706 const sizeIndex = maskIndex + 1; // location of size for skipping 74707 74708 updateOpCodes.push(null, null); // Alloc space for mask and size 74709 74710 const startIndex = maskIndex + 2; // location of first allocation. 74711 74712 if (ngDevMode) { 74713 attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString); 74714 } 74715 74716 const textParts = str.split(BINDING_REGEXP); 74717 let mask = 0; 74718 74719 for (let j = 0; j < textParts.length; j++) { 74720 const textValue = textParts[j]; 74721 74722 if (j & 1) { 74723 // Odd indexes are bindings 74724 const bindingIndex = bindingStart + parseInt(textValue, 10); 74725 updateOpCodes.push(-1 - bindingIndex); 74726 mask = mask | toMaskBit(bindingIndex); 74727 } else if (textValue !== '') { 74728 // Even indexes are text 74729 updateOpCodes.push(textValue); 74730 } 74731 } 74732 74733 updateOpCodes.push(destinationNode << 2 74734 /* I18nUpdateOpCode.SHIFT_REF */ 74735 | (attrName ? 1 74736 /* I18nUpdateOpCode.Attr */ 74737 : 0 74738 /* I18nUpdateOpCode.Text */ 74739 )); 74740 74741 if (attrName) { 74742 updateOpCodes.push(attrName, sanitizeFn); 74743 } 74744 74745 updateOpCodes[maskIndex] = mask; 74746 updateOpCodes[sizeIndex] = updateOpCodes.length - startIndex; 74747 return mask; 74748} 74749/** 74750 * Count the number of bindings in the given `opCodes`. 74751 * 74752 * It could be possible to speed this up, by passing the number of bindings found back from 74753 * `generateBindingUpdateOpCodes()` to `i18nAttributesFirstPass()` but this would then require more 74754 * complexity in the code and/or transient objects to be created. 74755 * 74756 * Since this function is only called once when the template is instantiated, is trivial in the 74757 * first instance (since `opCodes` will be an empty array), and it is not common for elements to 74758 * contain multiple i18n bound attributes, it seems like this is a reasonable compromise. 74759 */ 74760 74761 74762function countBindings(opCodes) { 74763 let count = 0; 74764 74765 for (let i = 0; i < opCodes.length; i++) { 74766 const opCode = opCodes[i]; // Bindings are negative numbers. 74767 74768 if (typeof opCode === 'number' && opCode < 0) { 74769 count++; 74770 } 74771 } 74772 74773 return count; 74774} 74775/** 74776 * Convert binding index to mask bit. 74777 * 74778 * Each index represents a single bit on the bit-mask. Because bit-mask only has 32 bits, we make 74779 * the 32nd bit share all masks for all bindings higher than 32. Since it is extremely rare to 74780 * have more than 32 bindings this will be hit very rarely. The downside of hitting this corner 74781 * case is that we will execute binding code more often than necessary. (penalty of performance) 74782 */ 74783 74784 74785function toMaskBit(bindingIndex) { 74786 return 1 << Math.min(bindingIndex, 31); 74787} 74788 74789function isRootTemplateMessage(subTemplateIndex) { 74790 return subTemplateIndex === -1; 74791} 74792/** 74793 * Removes everything inside the sub-templates of a message. 74794 */ 74795 74796 74797function removeInnerTemplateTranslation(message) { 74798 let match; 74799 let res = ''; 74800 let index = 0; 74801 let inTemplate = false; 74802 let tagMatched; 74803 74804 while ((match = SUBTEMPLATE_REGEXP.exec(message)) !== null) { 74805 if (!inTemplate) { 74806 res += message.substring(index, match.index + match[0].length); 74807 tagMatched = match[1]; 74808 inTemplate = true; 74809 } else { 74810 if (match[0] === `${MARKER}/*${tagMatched}${MARKER}`) { 74811 index = match.index; 74812 inTemplate = false; 74813 } 74814 } 74815 } 74816 74817 ngDevMode && assertEqual(inTemplate, false, `Tag mismatch: unable to find the end of the sub-template in the translation "${message}"`); 74818 res += message.slice(index); 74819 return res; 74820} 74821/** 74822 * Extracts a part of a message and removes the rest. 74823 * 74824 * This method is used for extracting a part of the message associated with a template. A 74825 * translated message can span multiple templates. 74826 * 74827 * Example: 74828 * ``` 74829 * <div i18n>Translate <span *ngIf>me</span>!</div> 74830 * ``` 74831 * 74832 * @param message The message to crop 74833 * @param subTemplateIndex Index of the sub-template to extract. If undefined it returns the 74834 * external template and removes all sub-templates. 74835 */ 74836 74837 74838function getTranslationForTemplate(message, subTemplateIndex) { 74839 if (isRootTemplateMessage(subTemplateIndex)) { 74840 // We want the root template message, ignore all sub-templates 74841 return removeInnerTemplateTranslation(message); 74842 } else { 74843 // We want a specific sub-template 74844 const start = message.indexOf(`:${subTemplateIndex}${MARKER}`) + 2 + subTemplateIndex.toString().length; 74845 const end = message.search(new RegExp(`${MARKER}\\/\\*\\d+:${subTemplateIndex}${MARKER}`)); 74846 return removeInnerTemplateTranslation(message.substring(start, end)); 74847 } 74848} 74849/** 74850 * Generate the OpCodes for ICU expressions. 74851 * 74852 * @param icuExpression 74853 * @param index Index where the anchor is stored and an optional `TIcuContainerNode` 74854 * - `lView[anchorIdx]` points to a `Comment` node representing the anchor for the ICU. 74855 * - `tView.data[anchorIdx]` points to the `TIcuContainerNode` if ICU is root (`null` otherwise) 74856 */ 74857 74858 74859function icuStart(tView, lView, updateOpCodes, parentIdx, icuExpression, anchorIdx) { 74860 ngDevMode && assertDefined(icuExpression, 'ICU expression must be defined'); 74861 let bindingMask = 0; 74862 const tIcu = { 74863 type: icuExpression.type, 74864 currentCaseLViewIndex: allocExpando(tView, lView, 1, null), 74865 anchorIdx, 74866 cases: [], 74867 create: [], 74868 remove: [], 74869 update: [] 74870 }; 74871 addUpdateIcuSwitch(updateOpCodes, icuExpression, anchorIdx); 74872 setTIcu(tView, anchorIdx, tIcu); 74873 const values = icuExpression.values; 74874 74875 for (let i = 0; i < values.length; i++) { 74876 // Each value is an array of strings & other ICU expressions 74877 const valueArr = values[i]; 74878 const nestedIcus = []; 74879 74880 for (let j = 0; j < valueArr.length; j++) { 74881 const value = valueArr[j]; 74882 74883 if (typeof value !== 'string') { 74884 // It is an nested ICU expression 74885 const icuIndex = nestedIcus.push(value) - 1; // Replace nested ICU expression by a comment node 74886 74887 valueArr[j] = `<!--�${icuIndex}�-->`; 74888 } 74889 } 74890 74891 bindingMask = parseIcuCase(tView, tIcu, lView, updateOpCodes, parentIdx, icuExpression.cases[i], valueArr.join(''), nestedIcus) | bindingMask; 74892 } 74893 74894 if (bindingMask) { 74895 addUpdateIcuUpdate(updateOpCodes, bindingMask, anchorIdx); 74896 } 74897} 74898/** 74899 * Parses text containing an ICU expression and produces a JSON object for it. 74900 * Original code from closure library, modified for Angular. 74901 * 74902 * @param pattern Text containing an ICU expression that needs to be parsed. 74903 * 74904 */ 74905 74906 74907function parseICUBlock(pattern) { 74908 const cases = []; 74909 const values = []; 74910 let icuType = 1 74911 /* IcuType.plural */ 74912 ; 74913 let mainBinding = 0; 74914 pattern = pattern.replace(ICU_BLOCK_REGEXP, function (str, binding, type) { 74915 if (type === 'select') { 74916 icuType = 0 74917 /* IcuType.select */ 74918 ; 74919 } else { 74920 icuType = 1 74921 /* IcuType.plural */ 74922 ; 74923 } 74924 74925 mainBinding = parseInt(binding.slice(1), 10); 74926 return ''; 74927 }); 74928 const parts = i18nParseTextIntoPartsAndICU(pattern); // Looking for (key block)+ sequence. One of the keys has to be "other". 74929 74930 for (let pos = 0; pos < parts.length;) { 74931 let key = parts[pos++].trim(); 74932 74933 if (icuType === 1 74934 /* IcuType.plural */ 74935 ) { 74936 // Key can be "=x", we just want "x" 74937 key = key.replace(/\s*(?:=)?(\w+)\s*/, '$1'); 74938 } 74939 74940 if (key.length) { 74941 cases.push(key); 74942 } 74943 74944 const blocks = i18nParseTextIntoPartsAndICU(parts[pos++]); 74945 74946 if (cases.length > values.length) { 74947 values.push(blocks); 74948 } 74949 } // TODO(ocombe): support ICU expressions in attributes, see #21615 74950 74951 74952 return { 74953 type: icuType, 74954 mainBinding: mainBinding, 74955 cases, 74956 values 74957 }; 74958} 74959/** 74960 * Breaks pattern into strings and top level {...} blocks. 74961 * Can be used to break a message into text and ICU expressions, or to break an ICU expression 74962 * into keys and cases. Original code from closure library, modified for Angular. 74963 * 74964 * @param pattern (sub)Pattern to be broken. 74965 * @returns An `Array<string|IcuExpression>` where: 74966 * - odd positions: `string` => text between ICU expressions 74967 * - even positions: `ICUExpression` => ICU expression parsed into `ICUExpression` record. 74968 */ 74969 74970 74971function i18nParseTextIntoPartsAndICU(pattern) { 74972 if (!pattern) { 74973 return []; 74974 } 74975 74976 let prevPos = 0; 74977 const braceStack = []; 74978 const results = []; 74979 const braces = /[{}]/g; // lastIndex doesn't get set to 0 so we have to. 74980 74981 braces.lastIndex = 0; 74982 let match; 74983 74984 while (match = braces.exec(pattern)) { 74985 const pos = match.index; 74986 74987 if (match[0] == '}') { 74988 braceStack.pop(); 74989 74990 if (braceStack.length == 0) { 74991 // End of the block. 74992 const block = pattern.substring(prevPos, pos); 74993 74994 if (ICU_BLOCK_REGEXP.test(block)) { 74995 results.push(parseICUBlock(block)); 74996 } else { 74997 results.push(block); 74998 } 74999 75000 prevPos = pos + 1; 75001 } 75002 } else { 75003 if (braceStack.length == 0) { 75004 const substring = pattern.substring(prevPos, pos); 75005 results.push(substring); 75006 prevPos = pos + 1; 75007 } 75008 75009 braceStack.push('{'); 75010 } 75011 } 75012 75013 const substring = pattern.substring(prevPos); 75014 results.push(substring); 75015 return results; 75016} 75017/** 75018 * Parses a node, its children and its siblings, and generates the mutate & update OpCodes. 75019 * 75020 */ 75021 75022 75023function parseIcuCase(tView, tIcu, lView, updateOpCodes, parentIdx, caseName, unsafeCaseHtml, nestedIcus) { 75024 const create = []; 75025 const remove = []; 75026 const update = []; 75027 75028 if (ngDevMode) { 75029 attachDebugGetter(create, icuCreateOpCodesToString); 75030 attachDebugGetter(remove, i18nRemoveOpCodesToString); 75031 attachDebugGetter(update, i18nUpdateOpCodesToString); 75032 } 75033 75034 tIcu.cases.push(caseName); 75035 tIcu.create.push(create); 75036 tIcu.remove.push(remove); 75037 tIcu.update.push(update); 75038 const inertBodyHelper = getInertBodyHelper(getDocument()); 75039 const inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeCaseHtml); 75040 ngDevMode && assertDefined(inertBodyElement, 'Unable to generate inert body element'); 75041 const inertRootNode = getTemplateContent(inertBodyElement) || inertBodyElement; 75042 75043 if (inertRootNode) { 75044 return walkIcuTree(tView, tIcu, lView, updateOpCodes, create, remove, update, inertRootNode, parentIdx, nestedIcus, 0); 75045 } else { 75046 return 0; 75047 } 75048} 75049 75050function walkIcuTree(tView, tIcu, lView, sharedUpdateOpCodes, create, remove, update, parentNode, parentIdx, nestedIcus, depth) { 75051 let bindingMask = 0; 75052 let currentNode = parentNode.firstChild; 75053 75054 while (currentNode) { 75055 const newIndex = allocExpando(tView, lView, 1, null); 75056 75057 switch (currentNode.nodeType) { 75058 case Node.ELEMENT_NODE: 75059 const element = currentNode; 75060 const tagName = element.tagName.toLowerCase(); 75061 75062 if (VALID_ELEMENTS.hasOwnProperty(tagName)) { 75063 addCreateNodeAndAppend(create, ELEMENT_MARKER, tagName, parentIdx, newIndex); 75064 tView.data[newIndex] = tagName; 75065 const elAttrs = element.attributes; 75066 75067 for (let i = 0; i < elAttrs.length; i++) { 75068 const attr = elAttrs.item(i); 75069 const lowerAttrName = attr.name.toLowerCase(); 75070 const hasBinding = !!attr.value.match(BINDING_REGEXP); // we assume the input string is safe, unless it's using a binding 75071 75072 if (hasBinding) { 75073 if (VALID_ATTRS.hasOwnProperty(lowerAttrName)) { 75074 if (URI_ATTRS[lowerAttrName]) { 75075 generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, _sanitizeUrl); 75076 } else { 75077 generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, null); 75078 } 75079 } else { 75080 ngDevMode && console.warn(`WARNING: ignoring unsafe attribute value ` + `${lowerAttrName} on element ${tagName} ` + `(see https://g.co/ng/security#xss)`); 75081 } 75082 } else { 75083 addCreateAttribute(create, newIndex, attr); 75084 } 75085 } // Parse the children of this node (if any) 75086 75087 75088 bindingMask = walkIcuTree(tView, tIcu, lView, sharedUpdateOpCodes, create, remove, update, currentNode, newIndex, nestedIcus, depth + 1) | bindingMask; 75089 addRemoveNode(remove, newIndex, depth); 75090 } 75091 75092 break; 75093 75094 case Node.TEXT_NODE: 75095 const value = currentNode.textContent || ''; 75096 const hasBinding = value.match(BINDING_REGEXP); 75097 addCreateNodeAndAppend(create, null, hasBinding ? '' : value, parentIdx, newIndex); 75098 addRemoveNode(remove, newIndex, depth); 75099 75100 if (hasBinding) { 75101 bindingMask = generateBindingUpdateOpCodes(update, value, newIndex, null, 0, null) | bindingMask; 75102 } 75103 75104 break; 75105 75106 case Node.COMMENT_NODE: 75107 // Check if the comment node is a placeholder for a nested ICU 75108 const isNestedIcu = NESTED_ICU.exec(currentNode.textContent || ''); 75109 75110 if (isNestedIcu) { 75111 const nestedIcuIndex = parseInt(isNestedIcu[1], 10); 75112 const icuExpression = nestedIcus[nestedIcuIndex]; // Create the comment node that will anchor the ICU expression 75113 75114 addCreateNodeAndAppend(create, ICU_MARKER, ngDevMode ? `nested ICU ${nestedIcuIndex}` : '', parentIdx, newIndex); 75115 icuStart(tView, lView, sharedUpdateOpCodes, parentIdx, icuExpression, newIndex); 75116 addRemoveNestedIcu(remove, newIndex, depth); 75117 } 75118 75119 break; 75120 } 75121 75122 currentNode = currentNode.nextSibling; 75123 } 75124 75125 return bindingMask; 75126} 75127 75128function addRemoveNode(remove, index, depth) { 75129 if (depth === 0) { 75130 remove.push(index); 75131 } 75132} 75133 75134function addRemoveNestedIcu(remove, index, depth) { 75135 if (depth === 0) { 75136 remove.push(~index); // remove ICU at `index` 75137 75138 remove.push(index); // remove ICU comment at `index` 75139 } 75140} 75141 75142function addUpdateIcuSwitch(update, icuExpression, index) { 75143 update.push(toMaskBit(icuExpression.mainBinding), 2, -1 - icuExpression.mainBinding, index << 2 75144 /* I18nUpdateOpCode.SHIFT_REF */ 75145 | 2 75146 /* I18nUpdateOpCode.IcuSwitch */ 75147 ); 75148} 75149 75150function addUpdateIcuUpdate(update, bindingMask, index) { 75151 update.push(bindingMask, 1, index << 2 75152 /* I18nUpdateOpCode.SHIFT_REF */ 75153 | 3 75154 /* I18nUpdateOpCode.IcuUpdate */ 75155 ); 75156} 75157 75158function addCreateNodeAndAppend(create, marker, text, appendToParentIdx, createAtIdx) { 75159 if (marker !== null) { 75160 create.push(marker); 75161 } 75162 75163 create.push(text, createAtIdx, icuCreateOpCode(0 75164 /* IcuCreateOpCode.AppendChild */ 75165 , appendToParentIdx, createAtIdx)); 75166} 75167 75168function addCreateAttribute(create, newIndex, attr) { 75169 create.push(newIndex << 1 75170 /* IcuCreateOpCode.SHIFT_REF */ 75171 | 1 75172 /* IcuCreateOpCode.Attr */ 75173 , attr.name, attr.value); 75174} 75175/** 75176 * @license 75177 * Copyright Google LLC All Rights Reserved. 75178 * 75179 * Use of this source code is governed by an MIT-style license that can be 75180 * found in the LICENSE file at https://angular.io/license 75181 */ 75182// i18nPostprocess consts 75183 75184 75185const ROOT_TEMPLATE_ID = 0; 75186const PP_MULTI_VALUE_PLACEHOLDERS_REGEXP = /\[(�.+?�?)\]/; 75187const PP_PLACEHOLDERS_REGEXP = /\[(�.+?�?)\]|(�\/?\*\d+:\d+�)/g; 75188const PP_ICU_VARS_REGEXP = /({\s*)(VAR_(PLURAL|SELECT)(_\d+)?)(\s*,)/g; 75189const PP_ICU_PLACEHOLDERS_REGEXP = /{([A-Z0-9_]+)}/g; 75190const PP_ICUS_REGEXP = /�I18N_EXP_(ICU(_\d+)?)�/g; 75191const PP_CLOSE_TEMPLATE_REGEXP = /\/\*/; 75192const PP_TEMPLATE_ID_REGEXP = /\d+\:(\d+)/; 75193/** 75194 * Handles message string post-processing for internationalization. 75195 * 75196 * Handles message string post-processing by transforming it from intermediate 75197 * format (that might contain some markers that we need to replace) to the final 75198 * form, consumable by i18nStart instruction. Post processing steps include: 75199 * 75200 * 1. Resolve all multi-value cases (like [�*1:1��#2:1�|�#4:1�|�5�]) 75201 * 2. Replace all ICU vars (like "VAR_PLURAL") 75202 * 3. Replace all placeholders used inside ICUs in a form of {PLACEHOLDER} 75203 * 4. Replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�) 75204 * in case multiple ICUs have the same placeholder name 75205 * 75206 * @param message Raw translation string for post processing 75207 * @param replacements Set of replacements that should be applied 75208 * 75209 * @returns Transformed string that can be consumed by i18nStart instruction 75210 * 75211 * @codeGenApi 75212 */ 75213 75214function i18nPostprocess(message, replacements = {}) { 75215 /** 75216 * Step 1: resolve all multi-value placeholders like [�#5�|�*1:1��#2:1�|�#4:1�] 75217 * 75218 * Note: due to the way we process nested templates (BFS), multi-value placeholders are typically 75219 * grouped by templates, for example: [�#5�|�#6�|�#1:1�|�#3:2�] where �#5� and �#6� belong to root 75220 * template, �#1:1� belong to nested template with index 1 and �#1:2� - nested template with index 75221 * 3. However in real templates the order might be different: i.e. �#1:1� and/or �#3:2� may go in 75222 * front of �#6�. The post processing step restores the right order by keeping track of the 75223 * template id stack and looks for placeholders that belong to the currently active template. 75224 */ 75225 let result = message; 75226 75227 if (PP_MULTI_VALUE_PLACEHOLDERS_REGEXP.test(message)) { 75228 const matches = {}; 75229 const templateIdsStack = [ROOT_TEMPLATE_ID]; 75230 result = result.replace(PP_PLACEHOLDERS_REGEXP, (m, phs, tmpl) => { 75231 const content = phs || tmpl; 75232 const placeholders = matches[content] || []; 75233 75234 if (!placeholders.length) { 75235 content.split('|').forEach(placeholder => { 75236 const match = placeholder.match(PP_TEMPLATE_ID_REGEXP); 75237 const templateId = match ? parseInt(match[1], 10) : ROOT_TEMPLATE_ID; 75238 const isCloseTemplateTag = PP_CLOSE_TEMPLATE_REGEXP.test(placeholder); 75239 placeholders.push([templateId, isCloseTemplateTag, placeholder]); 75240 }); 75241 matches[content] = placeholders; 75242 } 75243 75244 if (!placeholders.length) { 75245 throw new Error(`i18n postprocess: unmatched placeholder - ${content}`); 75246 } 75247 75248 const currentTemplateId = templateIdsStack[templateIdsStack.length - 1]; 75249 let idx = 0; // find placeholder index that matches current template id 75250 75251 for (let i = 0; i < placeholders.length; i++) { 75252 if (placeholders[i][0] === currentTemplateId) { 75253 idx = i; 75254 break; 75255 } 75256 } // update template id stack based on the current tag extracted 75257 75258 75259 const [templateId, isCloseTemplateTag, placeholder] = placeholders[idx]; 75260 75261 if (isCloseTemplateTag) { 75262 templateIdsStack.pop(); 75263 } else if (currentTemplateId !== templateId) { 75264 templateIdsStack.push(templateId); 75265 } // remove processed tag from the list 75266 75267 75268 placeholders.splice(idx, 1); 75269 return placeholder; 75270 }); 75271 } // return current result if no replacements specified 75272 75273 75274 if (!Object.keys(replacements).length) { 75275 return result; 75276 } 75277 /** 75278 * Step 2: replace all ICU vars (like "VAR_PLURAL") 75279 */ 75280 75281 75282 result = result.replace(PP_ICU_VARS_REGEXP, (match, start, key, _type, _idx, end) => { 75283 return replacements.hasOwnProperty(key) ? `${start}${replacements[key]}${end}` : match; 75284 }); 75285 /** 75286 * Step 3: replace all placeholders used inside ICUs in a form of {PLACEHOLDER} 75287 */ 75288 75289 result = result.replace(PP_ICU_PLACEHOLDERS_REGEXP, (match, key) => { 75290 return replacements.hasOwnProperty(key) ? replacements[key] : match; 75291 }); 75292 /** 75293 * Step 4: replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�) in case 75294 * multiple ICUs have the same placeholder name 75295 */ 75296 75297 result = result.replace(PP_ICUS_REGEXP, (match, key) => { 75298 if (replacements.hasOwnProperty(key)) { 75299 const list = replacements[key]; 75300 75301 if (!list.length) { 75302 throw new Error(`i18n postprocess: unmatched ICU - ${match} with key: ${key}`); 75303 } 75304 75305 return list.shift(); 75306 } 75307 75308 return match; 75309 }); 75310 return result; 75311} 75312/** 75313 * @license 75314 * Copyright Google LLC All Rights Reserved. 75315 * 75316 * Use of this source code is governed by an MIT-style license that can be 75317 * found in the LICENSE file at https://angular.io/license 75318 */ 75319 75320/** 75321 * Marks a block of text as translatable. 75322 * 75323 * The instructions `i18nStart` and `i18nEnd` mark the translation block in the template. 75324 * The translation `message` is the value which is locale specific. The translation string may 75325 * contain placeholders which associate inner elements and sub-templates within the translation. 75326 * 75327 * The translation `message` placeholders are: 75328 * - `�{index}(:{block})�`: *Binding Placeholder*: Marks a location where an expression will be 75329 * interpolated into. The placeholder `index` points to the expression binding index. An optional 75330 * `block` that matches the sub-template in which it was declared. 75331 * - `�#{index}(:{block})�`/`�/#{index}(:{block})�`: *Element Placeholder*: Marks the beginning 75332 * and end of DOM element that were embedded in the original translation block. The placeholder 75333 * `index` points to the element index in the template instructions set. An optional `block` that 75334 * matches the sub-template in which it was declared. 75335 * - `�*{index}:{block}�`/`�/*{index}:{block}�`: *Sub-template Placeholder*: Sub-templates must be 75336 * split up and translated separately in each angular template function. The `index` points to the 75337 * `template` instruction index. A `block` that matches the sub-template in which it was declared. 75338 * 75339 * @param index A unique index of the translation in the static block. 75340 * @param messageIndex An index of the translation message from the `def.consts` array. 75341 * @param subTemplateIndex Optional sub-template index in the `message`. 75342 * 75343 * @codeGenApi 75344 */ 75345 75346 75347function ɵɵi18nStart(index, messageIndex, subTemplateIndex = -1) { 75348 const tView = getTView(); 75349 const lView = getLView(); 75350 const adjustedIndex = HEADER_OFFSET + index; 75351 ngDevMode && assertDefined(tView, `tView should be defined`); 75352 const message = getConstant(tView.consts, messageIndex); 75353 const parentTNode = getCurrentParentTNode(); 75354 75355 if (tView.firstCreatePass) { 75356 i18nStartFirstCreatePass(tView, parentTNode === null ? 0 : parentTNode.index, lView, adjustedIndex, message, subTemplateIndex); 75357 } 75358 75359 const tI18n = tView.data[adjustedIndex]; 75360 const sameViewParentTNode = parentTNode === lView[T_HOST] ? null : parentTNode; 75361 const parentRNode = getClosestRElement(tView, sameViewParentTNode, lView); // If `parentTNode` is an `ElementContainer` than it has `<!--ng-container--->`. 75362 // When we do inserts we have to make sure to insert in front of `<!--ng-container--->`. 75363 75364 const insertInFrontOf = parentTNode && parentTNode.type & 8 75365 /* TNodeType.ElementContainer */ 75366 ? lView[parentTNode.index] : null; 75367 applyCreateOpCodes(lView, tI18n.create, parentRNode, insertInFrontOf); 75368 setInI18nBlock(true); 75369} 75370/** 75371 * Translates a translation block marked by `i18nStart` and `i18nEnd`. It inserts the text/ICU nodes 75372 * into the render tree, moves the placeholder nodes and removes the deleted nodes. 75373 * 75374 * @codeGenApi 75375 */ 75376 75377 75378function ɵɵi18nEnd() { 75379 setInI18nBlock(false); 75380} 75381/** 75382 * 75383 * Use this instruction to create a translation block that doesn't contain any placeholder. 75384 * It calls both {@link i18nStart} and {@link i18nEnd} in one instruction. 75385 * 75386 * The translation `message` is the value which is locale specific. The translation string may 75387 * contain placeholders which associate inner elements and sub-templates within the translation. 75388 * 75389 * The translation `message` placeholders are: 75390 * - `�{index}(:{block})�`: *Binding Placeholder*: Marks a location where an expression will be 75391 * interpolated into. The placeholder `index` points to the expression binding index. An optional 75392 * `block` that matches the sub-template in which it was declared. 75393 * - `�#{index}(:{block})�`/`�/#{index}(:{block})�`: *Element Placeholder*: Marks the beginning 75394 * and end of DOM element that were embedded in the original translation block. The placeholder 75395 * `index` points to the element index in the template instructions set. An optional `block` that 75396 * matches the sub-template in which it was declared. 75397 * - `�*{index}:{block}�`/`�/*{index}:{block}�`: *Sub-template Placeholder*: Sub-templates must be 75398 * split up and translated separately in each angular template function. The `index` points to the 75399 * `template` instruction index. A `block` that matches the sub-template in which it was declared. 75400 * 75401 * @param index A unique index of the translation in the static block. 75402 * @param messageIndex An index of the translation message from the `def.consts` array. 75403 * @param subTemplateIndex Optional sub-template index in the `message`. 75404 * 75405 * @codeGenApi 75406 */ 75407 75408 75409function ɵɵi18n(index, messageIndex, subTemplateIndex) { 75410 ɵɵi18nStart(index, messageIndex, subTemplateIndex); 75411 ɵɵi18nEnd(); 75412} 75413/** 75414 * Marks a list of attributes as translatable. 75415 * 75416 * @param index A unique index in the static block 75417 * @param values 75418 * 75419 * @codeGenApi 75420 */ 75421 75422 75423function ɵɵi18nAttributes(index, attrsIndex) { 75424 const tView = getTView(); 75425 ngDevMode && assertDefined(tView, `tView should be defined`); 75426 const attrs = getConstant(tView.consts, attrsIndex); 75427 i18nAttributesFirstPass(tView, index + HEADER_OFFSET, attrs); 75428} 75429/** 75430 * Stores the values of the bindings during each update cycle in order to determine if we need to 75431 * update the translated nodes. 75432 * 75433 * @param value The binding's value 75434 * @returns This function returns itself so that it may be chained 75435 * (e.g. `i18nExp(ctx.name)(ctx.title)`) 75436 * 75437 * @codeGenApi 75438 */ 75439 75440 75441function ɵɵi18nExp(value) { 75442 const lView = getLView(); 75443 setMaskBit(bindingUpdated(lView, nextBindingIndex(), value)); 75444 return ɵɵi18nExp; 75445} 75446/** 75447 * Updates a translation block or an i18n attribute when the bindings have changed. 75448 * 75449 * @param index Index of either {@link i18nStart} (translation block) or {@link i18nAttributes} 75450 * (i18n attribute) on which it should update the content. 75451 * 75452 * @codeGenApi 75453 */ 75454 75455 75456function ɵɵi18nApply(index) { 75457 applyI18n(getTView(), getLView(), index + HEADER_OFFSET); 75458} 75459/** 75460 * Handles message string post-processing for internationalization. 75461 * 75462 * Handles message string post-processing by transforming it from intermediate 75463 * format (that might contain some markers that we need to replace) to the final 75464 * form, consumable by i18nStart instruction. Post processing steps include: 75465 * 75466 * 1. Resolve all multi-value cases (like [�*1:1��#2:1�|�#4:1�|�5�]) 75467 * 2. Replace all ICU vars (like "VAR_PLURAL") 75468 * 3. Replace all placeholders used inside ICUs in a form of {PLACEHOLDER} 75469 * 4. Replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�) 75470 * in case multiple ICUs have the same placeholder name 75471 * 75472 * @param message Raw translation string for post processing 75473 * @param replacements Set of replacements that should be applied 75474 * 75475 * @returns Transformed string that can be consumed by i18nStart instruction 75476 * 75477 * @codeGenApi 75478 */ 75479 75480 75481function ɵɵi18nPostprocess(message, replacements = {}) { 75482 return i18nPostprocess(message, replacements); 75483} 75484/** 75485 * @license 75486 * Copyright Google LLC All Rights Reserved. 75487 * 75488 * Use of this source code is governed by an MIT-style license that can be 75489 * found in the LICENSE file at https://angular.io/license 75490 */ 75491 75492/** 75493 * @license 75494 * Copyright Google LLC All Rights Reserved. 75495 * 75496 * Use of this source code is governed by an MIT-style license that can be 75497 * found in the LICENSE file at https://angular.io/license 75498 */ 75499 75500/** 75501 * Resolves the providers which are defined in the DirectiveDef. 75502 * 75503 * When inserting the tokens and the factories in their respective arrays, we can assume that 75504 * this method is called first for the component (if any), and then for other directives on the same 75505 * node. 75506 * As a consequence,the providers are always processed in that order: 75507 * 1) The view providers of the component 75508 * 2) The providers of the component 75509 * 3) The providers of the other directives 75510 * This matches the structure of the injectables arrays of a view (for each node). 75511 * So the tokens and the factories can be pushed at the end of the arrays, except 75512 * in one case for multi providers. 75513 * 75514 * @param def the directive definition 75515 * @param providers: Array of `providers`. 75516 * @param viewProviders: Array of `viewProviders`. 75517 */ 75518 75519 75520function providersResolver(def, providers, viewProviders) { 75521 const tView = getTView(); 75522 75523 if (tView.firstCreatePass) { 75524 const isComponent = isComponentDef(def); // The list of view providers is processed first, and the flags are updated 75525 75526 resolveProvider(viewProviders, tView.data, tView.blueprint, isComponent, true); // Then, the list of providers is processed, and the flags are updated 75527 75528 resolveProvider(providers, tView.data, tView.blueprint, isComponent, false); 75529 } 75530} 75531/** 75532 * Resolves a provider and publishes it to the DI system. 75533 */ 75534 75535 75536function resolveProvider(provider, tInjectables, lInjectablesBlueprint, isComponent, isViewProvider) { 75537 provider = resolveForwardRef(provider); 75538 75539 if (Array.isArray(provider)) { 75540 // Recursively call `resolveProvider` 75541 // Recursion is OK in this case because this code will not be in hot-path once we implement 75542 // cloning of the initial state. 75543 for (let i = 0; i < provider.length; i++) { 75544 resolveProvider(provider[i], tInjectables, lInjectablesBlueprint, isComponent, isViewProvider); 75545 } 75546 } else { 75547 const tView = getTView(); 75548 const lView = getLView(); 75549 let token = isTypeProvider(provider) ? provider : resolveForwardRef(provider.provide); 75550 let providerFactory = providerToFactory(provider); 75551 const tNode = getCurrentTNode(); 75552 const beginIndex = tNode.providerIndexes & 1048575 75553 /* TNodeProviderIndexes.ProvidersStartIndexMask */ 75554 ; 75555 const endIndex = tNode.directiveStart; 75556 const cptViewProvidersCount = tNode.providerIndexes >> 20 75557 /* TNodeProviderIndexes.CptViewProvidersCountShift */ 75558 ; 75559 75560 if (isTypeProvider(provider) || !provider.multi) { 75561 // Single provider case: the factory is created and pushed immediately 75562 const factory = new NodeInjectorFactory(providerFactory, isViewProvider, ɵɵdirectiveInject); 75563 const existingFactoryIndex = indexOf(token, tInjectables, isViewProvider ? beginIndex : beginIndex + cptViewProvidersCount, endIndex); 75564 75565 if (existingFactoryIndex === -1) { 75566 diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, token); 75567 registerDestroyHooksIfSupported(tView, provider, tInjectables.length); 75568 tInjectables.push(token); 75569 tNode.directiveStart++; 75570 tNode.directiveEnd++; 75571 75572 if (isViewProvider) { 75573 tNode.providerIndexes += 1048576 75574 /* TNodeProviderIndexes.CptViewProvidersCountShifter */ 75575 ; 75576 } 75577 75578 lInjectablesBlueprint.push(factory); 75579 lView.push(factory); 75580 } else { 75581 lInjectablesBlueprint[existingFactoryIndex] = factory; 75582 lView[existingFactoryIndex] = factory; 75583 } 75584 } else { 75585 // Multi provider case: 75586 // We create a multi factory which is going to aggregate all the values. 75587 // Since the output of such a factory depends on content or view injection, 75588 // we create two of them, which are linked together. 75589 // 75590 // The first one (for view providers) is always in the first block of the injectables array, 75591 // and the second one (for providers) is always in the second block. 75592 // This is important because view providers have higher priority. When a multi token 75593 // is being looked up, the view providers should be found first. 75594 // Note that it is not possible to have a multi factory in the third block (directive block). 75595 // 75596 // The algorithm to process multi providers is as follows: 75597 // 1) If the multi provider comes from the `viewProviders` of the component: 75598 // a) If the special view providers factory doesn't exist, it is created and pushed. 75599 // b) Else, the multi provider is added to the existing multi factory. 75600 // 2) If the multi provider comes from the `providers` of the component or of another 75601 // directive: 75602 // a) If the multi factory doesn't exist, it is created and provider pushed into it. 75603 // It is also linked to the multi factory for view providers, if it exists. 75604 // b) Else, the multi provider is added to the existing multi factory. 75605 const existingProvidersFactoryIndex = indexOf(token, tInjectables, beginIndex + cptViewProvidersCount, endIndex); 75606 const existingViewProvidersFactoryIndex = indexOf(token, tInjectables, beginIndex, beginIndex + cptViewProvidersCount); 75607 const doesProvidersFactoryExist = existingProvidersFactoryIndex >= 0 && lInjectablesBlueprint[existingProvidersFactoryIndex]; 75608 const doesViewProvidersFactoryExist = existingViewProvidersFactoryIndex >= 0 && lInjectablesBlueprint[existingViewProvidersFactoryIndex]; 75609 75610 if (isViewProvider && !doesViewProvidersFactoryExist || !isViewProvider && !doesProvidersFactoryExist) { 75611 // Cases 1.a and 2.a 75612 diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, token); 75613 const factory = multiFactory(isViewProvider ? multiViewProvidersFactoryResolver : multiProvidersFactoryResolver, lInjectablesBlueprint.length, isViewProvider, isComponent, providerFactory); 75614 75615 if (!isViewProvider && doesViewProvidersFactoryExist) { 75616 lInjectablesBlueprint[existingViewProvidersFactoryIndex].providerFactory = factory; 75617 } 75618 75619 registerDestroyHooksIfSupported(tView, provider, tInjectables.length, 0); 75620 tInjectables.push(token); 75621 tNode.directiveStart++; 75622 tNode.directiveEnd++; 75623 75624 if (isViewProvider) { 75625 tNode.providerIndexes += 1048576 75626 /* TNodeProviderIndexes.CptViewProvidersCountShifter */ 75627 ; 75628 } 75629 75630 lInjectablesBlueprint.push(factory); 75631 lView.push(factory); 75632 } else { 75633 // Cases 1.b and 2.b 75634 const indexInFactory = multiFactoryAdd(lInjectablesBlueprint[isViewProvider ? existingViewProvidersFactoryIndex : existingProvidersFactoryIndex], providerFactory, !isViewProvider && isComponent); 75635 registerDestroyHooksIfSupported(tView, provider, existingProvidersFactoryIndex > -1 ? existingProvidersFactoryIndex : existingViewProvidersFactoryIndex, indexInFactory); 75636 } 75637 75638 if (!isViewProvider && isComponent && doesViewProvidersFactoryExist) { 75639 lInjectablesBlueprint[existingViewProvidersFactoryIndex].componentProviders++; 75640 } 75641 } 75642 } 75643} 75644/** 75645 * Registers the `ngOnDestroy` hook of a provider, if the provider supports destroy hooks. 75646 * @param tView `TView` in which to register the hook. 75647 * @param provider Provider whose hook should be registered. 75648 * @param contextIndex Index under which to find the context for the hook when it's being invoked. 75649 * @param indexInFactory Only required for `multi` providers. Index of the provider in the multi 75650 * provider factory. 75651 */ 75652 75653 75654function registerDestroyHooksIfSupported(tView, provider, contextIndex, indexInFactory) { 75655 const providerIsTypeProvider = isTypeProvider(provider); 75656 const providerIsClassProvider = isClassProvider(provider); 75657 75658 if (providerIsTypeProvider || providerIsClassProvider) { 75659 // Resolve forward references as `useClass` can hold a forward reference. 75660 const classToken = providerIsClassProvider ? resolveForwardRef(provider.useClass) : provider; 75661 const prototype = classToken.prototype; 75662 const ngOnDestroy = prototype.ngOnDestroy; 75663 75664 if (ngOnDestroy) { 75665 const hooks = tView.destroyHooks || (tView.destroyHooks = []); 75666 75667 if (!providerIsTypeProvider && provider.multi) { 75668 ngDevMode && assertDefined(indexInFactory, 'indexInFactory when registering multi factory destroy hook'); 75669 const existingCallbacksIndex = hooks.indexOf(contextIndex); 75670 75671 if (existingCallbacksIndex === -1) { 75672 hooks.push(contextIndex, [indexInFactory, ngOnDestroy]); 75673 } else { 75674 hooks[existingCallbacksIndex + 1].push(indexInFactory, ngOnDestroy); 75675 } 75676 } else { 75677 hooks.push(contextIndex, ngOnDestroy); 75678 } 75679 } 75680 } 75681} 75682/** 75683 * Add a factory in a multi factory. 75684 * @returns Index at which the factory was inserted. 75685 */ 75686 75687 75688function multiFactoryAdd(multiFactory, factory, isComponentProvider) { 75689 if (isComponentProvider) { 75690 multiFactory.componentProviders++; 75691 } 75692 75693 return multiFactory.multi.push(factory) - 1; 75694} 75695/** 75696 * Returns the index of item in the array, but only in the begin to end range. 75697 */ 75698 75699 75700function indexOf(item, arr, begin, end) { 75701 for (let i = begin; i < end; i++) { 75702 if (arr[i] === item) return i; 75703 } 75704 75705 return -1; 75706} 75707/** 75708 * Use this with `multi` `providers`. 75709 */ 75710 75711 75712function multiProvidersFactoryResolver(_, tData, lData, tNode) { 75713 return multiResolve(this.multi, []); 75714} 75715/** 75716 * Use this with `multi` `viewProviders`. 75717 * 75718 * This factory knows how to concatenate itself with the existing `multi` `providers`. 75719 */ 75720 75721 75722function multiViewProvidersFactoryResolver(_, tData, lView, tNode) { 75723 const factories = this.multi; 75724 let result; 75725 75726 if (this.providerFactory) { 75727 const componentCount = this.providerFactory.componentProviders; 75728 const multiProviders = getNodeInjectable(lView, lView[TVIEW], this.providerFactory.index, tNode); // Copy the section of the array which contains `multi` `providers` from the component 75729 75730 result = multiProviders.slice(0, componentCount); // Insert the `viewProvider` instances. 75731 75732 multiResolve(factories, result); // Copy the section of the array which contains `multi` `providers` from other directives 75733 75734 for (let i = componentCount; i < multiProviders.length; i++) { 75735 result.push(multiProviders[i]); 75736 } 75737 } else { 75738 result = []; // Insert the `viewProvider` instances. 75739 75740 multiResolve(factories, result); 75741 } 75742 75743 return result; 75744} 75745/** 75746 * Maps an array of factories into an array of values. 75747 */ 75748 75749 75750function multiResolve(factories, result) { 75751 for (let i = 0; i < factories.length; i++) { 75752 const factory = factories[i]; 75753 result.push(factory()); 75754 } 75755 75756 return result; 75757} 75758/** 75759 * Creates a multi factory. 75760 */ 75761 75762 75763function multiFactory(factoryFn, index, isViewProvider, isComponent, f) { 75764 const factory = new NodeInjectorFactory(factoryFn, isViewProvider, ɵɵdirectiveInject); 75765 factory.multi = []; 75766 factory.index = index; 75767 factory.componentProviders = 0; 75768 multiFactoryAdd(factory, f, isComponent && !isViewProvider); 75769 return factory; 75770} 75771/** 75772 * This feature resolves the providers of a directive (or component), 75773 * and publish them into the DI system, making it visible to others for injection. 75774 * 75775 * For example: 75776 * ```ts 75777 * class ComponentWithProviders { 75778 * constructor(private greeter: GreeterDE) {} 75779 * 75780 * static ɵcmp = defineComponent({ 75781 * type: ComponentWithProviders, 75782 * selectors: [['component-with-providers']], 75783 * factory: () => new ComponentWithProviders(directiveInject(GreeterDE as any)), 75784 * decls: 1, 75785 * vars: 1, 75786 * template: function(fs: RenderFlags, ctx: ComponentWithProviders) { 75787 * if (fs & RenderFlags.Create) { 75788 * ɵɵtext(0); 75789 * } 75790 * if (fs & RenderFlags.Update) { 75791 * ɵɵtextInterpolate(ctx.greeter.greet()); 75792 * } 75793 * }, 75794 * features: [ɵɵProvidersFeature([GreeterDE])] 75795 * }); 75796 * } 75797 * ``` 75798 * 75799 * @param definition 75800 * 75801 * @codeGenApi 75802 */ 75803 75804 75805function ɵɵProvidersFeature(providers, viewProviders = []) { 75806 return definition => { 75807 definition.providersResolver = (def, processProvidersFn) => { 75808 return providersResolver(def, // 75809 processProvidersFn ? processProvidersFn(providers) : providers, // 75810 viewProviders); 75811 }; 75812 }; 75813} 75814/** 75815 * @license 75816 * Copyright Google LLC All Rights Reserved. 75817 * 75818 * Use of this source code is governed by an MIT-style license that can be 75819 * found in the LICENSE file at https://angular.io/license 75820 */ 75821 75822/** 75823 * Represents an instance of an `NgModule` created by an `NgModuleFactory`. 75824 * Provides access to the `NgModule` instance and related objects. 75825 * 75826 * @publicApi 75827 */ 75828 75829 75830class NgModuleRef$1 {} 75831/** 75832 * @publicApi 75833 * 75834 * @deprecated 75835 * This class was mostly used as a part of ViewEngine-based JIT API and is no longer needed in Ivy 75836 * JIT mode. See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) 75837 * for additional context. Angular provides APIs that accept NgModule classes directly (such as 75838 * [PlatformRef.bootstrapModule](api/core/PlatformRef#bootstrapModule) and 75839 * [createNgModule](api/core/createNgModule)), consider switching to those APIs instead of 75840 * using factory-based ones. 75841 */ 75842 75843 75844class NgModuleFactory$1 {} 75845/** 75846 * @license 75847 * Copyright Google LLC All Rights Reserved. 75848 * 75849 * Use of this source code is governed by an MIT-style license that can be 75850 * found in the LICENSE file at https://angular.io/license 75851 */ 75852 75853/** 75854 * Returns a new NgModuleRef instance based on the NgModule class and parent injector provided. 75855 * 75856 * @param ngModule NgModule class. 75857 * @param parentInjector Optional injector instance to use as a parent for the module injector. If 75858 * not provided, `NullInjector` will be used instead. 75859 * @returns NgModuleRef that represents an NgModule instance. 75860 * 75861 * @publicApi 75862 */ 75863 75864 75865function createNgModule(ngModule, parentInjector) { 75866 return new NgModuleRef(ngModule, parentInjector ?? null); 75867} 75868/** 75869 * The `createNgModule` function alias for backwards-compatibility. 75870 * Please avoid using it directly and use `createNgModule` instead. 75871 * 75872 * @deprecated Use `createNgModule` instead. 75873 */ 75874 75875 75876const createNgModuleRef = createNgModule; 75877 75878class NgModuleRef extends NgModuleRef$1 { 75879 constructor(ngModuleType, _parent) { 75880 super(); 75881 this._parent = _parent; // tslint:disable-next-line:require-internal-with-underscore 75882 75883 this._bootstrapComponents = []; 75884 this.destroyCbs = []; // When bootstrapping a module we have a dependency graph that looks like this: 75885 // ApplicationRef -> ComponentFactoryResolver -> NgModuleRef. The problem is that if the 75886 // module being resolved tries to inject the ComponentFactoryResolver, it'll create a 75887 // circular dependency which will result in a runtime error, because the injector doesn't 75888 // exist yet. We work around the issue by creating the ComponentFactoryResolver ourselves 75889 // and providing it, rather than letting the injector resolve it. 75890 75891 this.componentFactoryResolver = new ComponentFactoryResolver(this); 75892 const ngModuleDef = getNgModuleDef(ngModuleType); 75893 ngDevMode && assertDefined(ngModuleDef, `NgModule '${stringify(ngModuleType)}' is not a subtype of 'NgModuleType'.`); 75894 this._bootstrapComponents = maybeUnwrapFn(ngModuleDef.bootstrap); 75895 this._r3Injector = createInjectorWithoutInjectorInstances(ngModuleType, _parent, [{ 75896 provide: NgModuleRef$1, 75897 useValue: this 75898 }, {
75899 provide: ComponentFactoryResolver$1, 75900 useValue: this.componentFactoryResolver 75901 }], stringify(ngModuleType), new Set(['environment'])); // We need to resolve the injector types separately from the injector creation, because 75902 // the module might be trying to use this ref in its constructor for DI which will cause a 75903 // circular error that will eventually error out, because the injector isn't created yet. 75904 75905 this._r3Injector.resolveInjectorInitializers(); 75906 75907 this.instance = this._r3Injector.get(ngModuleType); 75908 } 75909 75910 get injector() { 75911 return this._r3Injector; 75912 } 75913 75914 destroy() { 75915 ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed'); 75916 const injector = this._r3Injector; 75917 !injector.destroyed && injector.destroy(); 75918 this.destroyCbs.forEach(fn => fn()); 75919 this.destroyCbs = null; 75920 } 75921 75922 onDestroy(callback) { 75923 ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed'); 75924 this.destroyCbs.push(callback); 75925 } 75926 75927} 75928 75929class NgModuleFactory extends NgModuleFactory$1 { 75930 constructor(moduleType) { 75931 super(); 75932 this.moduleType = moduleType; 75933 } 75934 75935 create(parentInjector) { 75936 return new NgModuleRef(this.moduleType, parentInjector); 75937 } 75938 75939} 75940 75941class EnvironmentNgModuleRefAdapter extends NgModuleRef$1 { 75942 constructor(providers, parent, source) { 75943 super(); 75944 this.componentFactoryResolver = new ComponentFactoryResolver(this); 75945 this.instance = null; 75946 const injector = new R3Injector([...providers, { 75947 provide: NgModuleRef$1, 75948 useValue: this 75949 }, { 75950 provide: ComponentFactoryResolver$1, 75951 useValue: this.componentFactoryResolver 75952 }], parent || getNullInjector(), source, new Set(['environment'])); 75953 this.injector = injector; 75954 injector.resolveInjectorInitializers(); 75955 } 75956 75957 destroy() { 75958 this.injector.destroy(); 75959 } 75960 75961 onDestroy(callback) { 75962 this.injector.onDestroy(callback); 75963 } 75964 75965} 75966/** 75967 * Create a new environment injector. 75968 * 75969 * Learn more about environment injectors in 75970 * [this guide](guide/standalone-components#environment-injectors). 75971 * 75972 * @param providers An array of providers. 75973 * @param parent A parent environment injector. 75974 * @param debugName An optional name for this injector instance, which will be used in error 75975 * messages. 75976 * 75977 * @publicApi 75978 * @developerPreview 75979 */ 75980 75981 75982function createEnvironmentInjector(providers, parent, debugName = null) { 75983 const adapter = new EnvironmentNgModuleRefAdapter(providers, parent, debugName); 75984 return adapter.injector; 75985} 75986/** 75987 * @license 75988 * Copyright Google LLC All Rights Reserved. 75989 * 75990 * Use of this source code is governed by an MIT-style license that can be 75991 * found in the LICENSE file at https://angular.io/license 75992 */ 75993 75994/** 75995 * A service used by the framework to create instances of standalone injectors. Those injectors are 75996 * created on demand in case of dynamic component instantiation and contain ambient providers 75997 * collected from the imports graph rooted at a given standalone component. 75998 */ 75999 76000 76001class StandaloneService { 76002 constructor(_injector) { 76003 this._injector = _injector; 76004 this.cachedInjectors = new Map(); 76005 } 76006 76007 getOrCreateStandaloneInjector(componentDef) { 76008 if (!componentDef.standalone) { 76009 return null; 76010 } 76011 76012 if (!this.cachedInjectors.has(componentDef.id)) { 76013 const providers = internalImportProvidersFrom(false, componentDef.type); 76014 const standaloneInjector = providers.length > 0 ? createEnvironmentInjector([providers], this._injector, `Standalone[${componentDef.type.name}]`) : null; 76015 this.cachedInjectors.set(componentDef.id, standaloneInjector); 76016 } 76017 76018 return this.cachedInjectors.get(componentDef.id); 76019 } 76020 76021 ngOnDestroy() { 76022 try { 76023 for (const injector of this.cachedInjectors.values()) { 76024 if (injector !== null) { 76025 injector.destroy(); 76026 } 76027 } 76028 } finally { 76029 this.cachedInjectors.clear(); 76030 } 76031 } 76032 76033} 76034/** @nocollapse */ 76035 76036 76037StandaloneService.ɵprov = ɵɵdefineInjectable({ 76038 token: StandaloneService, 76039 providedIn: 'environment', 76040 factory: () => new StandaloneService(ɵɵinject(EnvironmentInjector)) 76041}); 76042/** 76043 * A feature that acts as a setup code for the {@link StandaloneService}. 76044 * 76045 * The most important responsibility of this feature is to expose the "getStandaloneInjector" 76046 * function (an entry points to a standalone injector creation) on a component definition object. We
vendor: 5,134 bytes, lines 76047-76220
76047 * go through the features infrastructure to make sure that the standalone injector creation logic 76048 * is tree-shakable and not included in applications that don't use standalone components. 76049 * 76050 * @codeGenApi 76051 */ 76052 76053function ɵɵStandaloneFeature(definition) { 76054 definition.getStandaloneInjector = parentInjector => { 76055 return parentInjector.get(StandaloneService).getOrCreateStandaloneInjector(definition); 76056 }; 76057} 76058/** 76059 * @license 76060 * Copyright Google LLC All Rights Reserved. 76061 * 76062 * Use of this source code is governed by an MIT-style license that can be 76063 * found in the LICENSE file at https://angular.io/license 76064 */ 76065 76066/** 76067 * Retrieves the component instance associated with a given DOM element. 76068 * 76069 * @usageNotes 76070 * Given the following DOM structure: 76071 * 76072 * ```html 76073 * <app-root> 76074 * <div> 76075 * <child-comp></child-comp> 76076 * </div> 76077 * </app-root> 76078 * ``` 76079 * 76080 * Calling `getComponent` on `<child-comp>` will return the instance of `ChildComponent` 76081 * associated with this DOM element. 76082 * 76083 * Calling the function on `<app-root>` will return the `MyApp` instance. 76084 * 76085 * 76086 * @param element DOM element from which the component should be retrieved. 76087 * @returns Component instance associated with the element or `null` if there 76088 * is no component associated with it. 76089 * 76090 * @publicApi 76091 * @globalApi ng 76092 */ 76093 76094 76095function getComponent(element) { 76096 ngDevMode && assertDomElement(element); 76097 const context = getLContext(element); 76098 if (context === null) return null; 76099 76100 if (context.component === undefined) { 76101 const lView = context.lView; 76102 76103 if (lView === null) { 76104 return null; 76105 } 76106 76107 context.component = getComponentAtNodeIndex(context.nodeIndex, lView); 76108 } 76109 76110 return context.component; 76111} 76112/** 76113 * If inside an embedded view (e.g. `*ngIf` or `*ngFor`), retrieves the context of the embedded 76114 * view that the element is part of. Otherwise retrieves the instance of the component whose view 76115 * owns the element (in this case, the result is the same as calling `getOwningComponent`). 76116 * 76117 * @param element Element for which to get the surrounding component instance. 76118 * @returns Instance of the component that is around the element or null if the element isn't 76119 * inside any component. 76120 * 76121 * @publicApi 76122 * @globalApi ng 76123 */ 76124 76125 76126function getContext(element) { 76127 assertDomElement(element); 76128 const context = getLContext(element); 76129 const lView = context ? context.lView : null; 76130 return lView === null ? null : lView[CONTEXT]; 76131} 76132/** 76133 * Retrieves the component instance whose view contains the DOM element. 76134 * 76135 * For example, if `<child-comp>` is used in the template of `<app-comp>` 76136 * (i.e. a `ViewChild` of `<app-comp>`), calling `getOwningComponent` on `<child-comp>` 76137 * would return `<app-comp>`. 76138 * 76139 * @param elementOrDir DOM element, component or directive instance 76140 * for which to retrieve the root components. 76141 * @returns Component instance whose view owns the DOM element or null if the element is not 76142 * part of a component view. 76143 * 76144 * @publicApi 76145 * @globalApi ng 76146 */ 76147 76148 76149function getOwningComponent(elementOrDir) { 76150 const context = getLContext(elementOrDir); 76151 let lView = context ? context.lView : null; 76152 if (lView === null) return null; 76153 let parent; 76154 76155 while (lView[TVIEW].type === 2 76156 /* TViewType.Embedded */ 76157 && (parent = getLViewParent(lView))) { 76158 lView = parent; 76159 } 76160 76161 return lView[FLAGS] & 256 76162 /* LViewFlags.IsRoot */ 76163 ? null : lView[CONTEXT]; 76164} 76165/** 76166 * Retrieves all root components associated with a DOM element, directive or component instance. 76167 * Root components are those which have been bootstrapped by Angular. 76168 * 76169 * @param elementOrDir DOM element, component or directive instance 76170 * for which to retrieve the root components. 76171 * @returns Root components associated with the target object. 76172 * 76173 * @publicApi 76174 * @globalApi ng 76175 */ 76176 76177 76178function getRootComponents(elementOrDir) { 76179 const lView = readPatchedLView(elementOrDir); 76180 return lView !== null ? [getRootContext(lView)] : []; 76181} 76182/** 76183 * Retrieves an `Injector` associated with an element, component or directive instance. 76184 * 76185 * @param elementOrDir DOM element, component or directive instance for which to 76186 * retrieve the injector. 76187 * @returns Injector associated with the element, component or directive instance. 76188 * 76189 * @publicApi 76190 * @globalApi ng 76191 */ 76192 76193 76194function getInjector(elementOrDir) { 76195 const context = getLContext(elementOrDir); 76196 const lView = context ? context.lView : null; 76197 if (lView === null) return Injector.NULL; 76198 const tNode = lView[TVIEW].data[context.nodeIndex]; 76199 return new NodeInjector(tNode, lView); 76200} 76201/** 76202 * Retrieve a set of injection tokens at a given DOM node. 76203 * 76204 * @param element Element for which the injection tokens should be retrieved. 76205 */ 76206 76207 76208function getInjectionTokens(element) { 76209 const context = getLContext(element); 76210 const lView = context ? context.lView : null; 76211 if (lView === null) return []; 76212 const tView = lView[TVIEW]; 76213 const tNode = tView.data[context.nodeIndex]; 76214 const providerTokens = []; 76215 const startIndex = tNode.providerIndexes & 1048575 76216 /* TNodeProviderIndexes.ProvidersStartIndexMask */ 76217 ; 76218 const endIndex = tNode.directiveEnd; 76219 76220 for (let i = startIndex; i < endIndex; i++) {
76221 let value = tView.data[i]; 76222 76223 if (isDirectiveDefHack(value)) { 76224 // The fact that we sometimes store Type and sometimes DirectiveDef in this location is a 76225 // design flaw. We should always store same type so that we can be monomorphic. The issue 76226 // is that for Components/Directives we store the def instead the type. The correct behavior 76227 // is that we should always be storing injectable type in this location. 76228 value = value.type; 76229 } 76230 76231 providerTokens.push(value); 76232 } 76233 76234 return providerTokens; 76235} 76236/** 76237 * Retrieves directive instances associated with a given DOM node. Does not include 76238 * component instances. 76239 * 76240 * @usageNotes 76241 * Given the following DOM structure: 76242 * 76243 * ```html 76244 * <app-root> 76245 * <button my-button></button> 76246 * <my-comp></my-comp> 76247 * </app-root> 76248 * ``` 76249 * 76250 * Calling `getDirectives` on `<button>` will return an array with an instance of the `MyButton` 76251 * directive that is associated with the DOM node. 76252 * 76253 * Calling `getDirectives` on `<my-comp>` will return an empty array. 76254 * 76255 * @param node DOM node for which to get the directives. 76256 * @returns Array of directives associated with the node. 76257 * 76258 * @publicApi 76259 * @globalApi ng 76260 */ 76261 76262 76263function getDirectives(node) { 76264 // Skip text nodes because we can't have directives associated with them. 76265 if (node instanceof Text) { 76266 return []; 76267 } 76268 76269 const context = getLContext(node); 76270 const lView = context ? context.lView : null; 76271 76272 if (lView === null) { 76273 return []; 76274 } 76275 76276 const tView = lView[TVIEW]; 76277 const nodeIndex = context.nodeIndex; 76278 76279 if (!tView?.data[nodeIndex]) { 76280 return []; 76281 } 76282 76283 if (context.directives === undefined) { 76284 context.directives = getDirectivesAtNodeIndex(nodeIndex, lView, false); 76285 } // The `directives` in this case are a named array called `LComponentView`. Clone the 76286 // result so we don't expose an internal data structure in the user's console. 76287 76288 76289 return context.directives === null ? [] : [...context.directives]; 76290} 76291/** 76292 * Returns the debug (partial) metadata for a particular directive or component instance. 76293 * The function accepts an instance of a directive or component and returns the corresponding 76294 * metadata. 76295 * 76296 * @param directiveOrComponentInstance Instance of a directive or component 76297 * @returns metadata of the passed directive or component 76298 * 76299 * @publicApi 76300 * @globalApi ng 76301 */ 76302 76303 76304function getDirectiveMetadata$1(directiveOrComponentInstance) { 76305 const { 76306 constructor 76307 } = directiveOrComponentInstance; 76308 76309 if (!constructor) { 76310 throw new Error('Unable to find the instance constructor'); 76311 } // In case a component inherits from a directive, we may have component and directive metadata 76312 // To ensure we don't get the metadata of the directive, we want to call `getComponentDef` first. 76313 76314 76315 const componentDef = getComponentDef(constructor); 76316 76317 if (componentDef) { 76318 return { 76319 inputs: componentDef.inputs, 76320 outputs: componentDef.outputs, 76321 encapsulation: componentDef.encapsulation, 76322 changeDetection: componentDef.onPush ? ChangeDetectionStrategy.OnPush : ChangeDetectionStrategy.Default 76323 }; 76324 } 76325 76326 const directiveDef = getDirectiveDef(constructor); 76327 76328 if (directiveDef) { 76329 return { 76330 inputs: directiveDef.inputs, 76331 outputs: directiveDef.outputs 76332 }; 76333 } 76334 76335 return null; 76336} 76337/** 76338 * Retrieve map of local references. 76339 * 76340 * The references are retrieved as a map of local reference name to element or directive instance. 76341 * 76342 * @param target DOM element, component or directive instance for which to retrieve 76343 * the local references. 76344 */ 76345 76346 76347function getLocalRefs(target) { 76348 const context = getLContext(target); 76349 if (context === null) return {}; 76350 76351 if (context.localRefs === undefined) { 76352 const lView = context.lView; 76353 76354 if (lView === null) { 76355 return {}; 76356 } 76357 76358 context.localRefs = discoverLocalRefs(lView, context.nodeIndex); 76359 } 76360 76361 return context.localRefs || {}; 76362} 76363/** 76364 * Retrieves the host element of a component or directive instance. 76365 * The host element is the DOM element that matched the selector of the directive. 76366 * 76367 * @param componentOrDirective Component or directive instance for which the host 76368 * element should be retrieved. 76369 * @returns Host element of the target. 76370 * 76371 * @publicApi 76372 * @globalApi ng 76373 */ 76374 76375 76376function getHostElement(componentOrDirective) { 76377 return getLContext(componentOrDirective).native; 76378} 76379/** 76380 * Retrieves the rendered text for a given component. 76381 * 76382 * This function retrieves the host element of a component and 76383 * and then returns the `textContent` for that element. This implies 76384 * that the text returned will include re-projected content of 76385 * the component as well. 76386 * 76387 * @param component The component to return the content text for. 76388 */ 76389 76390 76391function getRenderedText(component) { 76392 const hostElement = getHostElement(component); 76393 return hostElement.textContent || ''; 76394} 76395/** 76396 * Retrieves a list of event listeners associated with a DOM element. The list does include host 76397 * listeners, but it does not include event listeners defined outside of the Angular context 76398 * (e.g. through `addEventListener`). 76399 * 76400 * @usageNotes 76401 * Given the following DOM structure: 76402 * 76403 * ```html 76404 * <app-root> 76405 * <div (click)="doSomething()"></div> 76406 * </app-root> 76407 * ``` 76408 * 76409 * Calling `getListeners` on `<div>` will return an object that looks as follows: 76410 * 76411 * ```ts 76412 * { 76413 * name: 'click', 76414 * element: <div>, 76415 * callback: () => doSomething(), 76416 * useCapture: false 76417 * } 76418 * ``` 76419 * 76420 * @param element Element for which the DOM listeners should be retrieved. 76421 * @returns Array of event listeners on the DOM element. 76422 * 76423 * @publicApi 76424 * @globalApi ng 76425 */ 76426 76427 76428function getListeners(element) { 76429 ngDevMode && assertDomElement(element); 76430 const lContext = getLContext(element); 76431 const lView = lContext === null ? null : lContext.lView; 76432 if (lView === null) return []; 76433 const tView = lView[TVIEW]; 76434 const lCleanup = lView[CLEANUP]; 76435 const tCleanup = tView.cleanup; 76436 const listeners = []; 76437 76438 if (tCleanup && lCleanup) { 76439 for (let i = 0; i < tCleanup.length;) { 76440 const firstParam = tCleanup[i++]; 76441 const secondParam = tCleanup[i++]; 76442 76443 if (typeof firstParam === 'string') { 76444 const name = firstParam; 76445 const listenerElement = unwrapRNode(lView[secondParam]); 76446 const callback = lCleanup[tCleanup[i++]]; 76447 const useCaptureOrIndx = tCleanup[i++]; // if useCaptureOrIndx is boolean then report it as is. 76448 // if useCaptureOrIndx is positive number then it in unsubscribe method 76449 // if useCaptureOrIndx is negative number then it is a Subscription 76450 76451 const type = typeof useCaptureOrIndx === 'boolean' || useCaptureOrIndx >= 0 ? 'dom' : 'output'; 76452 const useCapture = typeof useCaptureOrIndx === 'boolean' ? useCaptureOrIndx : false;
76453 76454 if (element == listenerElement) { 76455 listeners.push({ 76456 element, 76457 name, 76458 callback, 76459 useCapture, 76460 type 76461 }); 76462 } 76463 } 76464 } 76465 } 76466 76467 listeners.sort(sortListeners); 76468 return listeners; 76469} 76470 76471function sortListeners(a, b) { 76472 if (a.name == b.name) return 0; 76473 return a.name < b.name ? -1 : 1; 76474} 76475/** 76476 * This function should not exist because it is megamorphic and only mostly correct. 76477 * 76478 * See call site for more info. 76479 */ 76480 76481 76482function isDirectiveDefHack(obj) { 76483 return obj.type !== undefined && obj.template !== undefined && obj.declaredInputs !== undefined; 76484} 76485/** 76486 * Returns the attached `DebugNode` instance for an element in the DOM. 76487 * 76488 * @param element DOM element which is owned by an existing component's view. 76489 */ 76490 76491 76492function getDebugNode$1(element) { 76493 if (ngDevMode && !(element instanceof Node)) { 76494 throw new Error('Expecting instance of DOM Element'); 76495 } 76496 76497 const lContext = getLContext(element); 76498 const lView = lContext ? lContext.lView : null; 76499 76500 if (lView === null) { 76501 return null; 76502 } 76503 76504 const nodeIndex = lContext.nodeIndex; 76505 76506 if (nodeIndex !== -1) { 76507 const valueInLView = lView[nodeIndex]; // this means that value in the lView is a component with its own 76508 // data. In this situation the TNode is not accessed at the same spot. 76509 76510 const tNode = isLView(valueInLView) ? valueInLView[T_HOST] : getTNode(lView[TVIEW], nodeIndex); 76511 ngDevMode && assertEqual(tNode.index, nodeIndex, 'Expecting that TNode at index is same as index'); 76512 return buildDebugNode(tNode, lView); 76513 } 76514 76515 return null; 76516} 76517/** 76518 * Retrieve the component `LView` from component/element. 76519 * 76520 * NOTE: `LView` is a private and should not be leaked outside. 76521 * Don't export this method to `ng.*` on window. 76522 * 76523 * @param target DOM element or component instance for which to retrieve the LView. 76524 */ 76525 76526 76527function getComponentLView(target) { 76528 const lContext = getLContext(target); 76529 const nodeIndx = lContext.nodeIndex; 76530 const lView = lContext.lView; 76531 ngDevMode && assertLView(lView); 76532 const componentLView = lView[nodeIndx]; 76533 ngDevMode && assertLView(componentLView); 76534 return componentLView; 76535} 76536/** Asserts that a value is a DOM Element. */ 76537 76538 76539function assertDomElement(value) { 76540 if (typeof Element !== 'undefined' && !(value instanceof Element)) { 76541 throw new Error('Expecting instance of DOM Element'); 76542 } 76543} 76544/** 76545 * @license 76546 * Copyright Google LLC All Rights Reserved. 76547 * 76548 * Use of this source code is governed by an MIT-style license that can be 76549 * found in the LICENSE file at https://angular.io/license 76550 */ 76551 76552/** 76553 * Adds decorator, constructor, and property metadata to a given type via static metadata fields 76554 * on the type. 76555 * 76556 * These metadata fields can later be read with Angular's `ReflectionCapabilities` API. 76557 * 76558 * Calls to `setClassMetadata` can be guarded by ngDevMode, resulting in the metadata assignments 76559 * being tree-shaken away during production builds. 76560 */ 76561 76562 76563function setClassMetadata(type, decorators, ctorParameters, propDecorators) { 76564 return noSideEffects(() => { 76565 const clazz = type; 76566 76567 if (decorators !== null) { 76568 if (clazz.hasOwnProperty('decorators') && clazz.decorators !== undefined) { 76569 clazz.decorators.push(...decorators); 76570 } else { 76571 clazz.decorators = decorators; 76572 } 76573 } 76574 76575 if (ctorParameters !== null) { 76576 // Rather than merging, clobber the existing parameters. If other projects exist which 76577 // use tsickle-style annotations and reflect over them in the same way, this could 76578 // cause issues, but that is vanishingly unlikely. 76579 clazz.ctorParameters = ctorParameters; 76580 } 76581 76582 if (propDecorators !== null) { 76583 // The property decorator objects are merged as it is possible different fields have 76584 // different decorator types. Decorators on individual fields are not merged, as it's 76585 // also incredibly unlikely that a field will be decorated both with an Angular 76586 // decorator and a non-Angular decorator that's also been downleveled. 76587 if (clazz.hasOwnProperty('propDecorators') && clazz.propDecorators !== undefined) { 76588 clazz.propDecorators = { ...clazz.propDecorators, 76589 ...propDecorators 76590 }; 76591 } else { 76592 clazz.propDecorators = propDecorators; 76593 } 76594 } 76595 }); 76596} 76597/** 76598 * @license 76599 * Copyright Google LLC All Rights Reserved. 76600 * 76601 * Use of this source code is governed by an MIT-style license that can be 76602 * found in the LICENSE file at https://angular.io/license 76603 */ 76604 76605/** 76606 * Bindings for pure functions are stored after regular bindings. 76607 * 76608 * |-------decls------|---------vars---------| |----- hostVars (dir1) ------| 76609 * ------------------------------------------------------------------------------------------ 76610 * | nodes/refs/pipes | bindings | fn slots | injector | dir1 | host bindings | host slots | 76611 * ------------------------------------------------------------------------------------------ 76612 * ^ ^ 76613 * TView.bindingStartIndex TView.expandoStartIndex 76614 * 76615 * Pure function instructions are given an offset from the binding root. Adding the offset to the 76616 * binding root gives the first index where the bindings are stored. In component views, the binding 76617 * root is the bindingStartIndex. In host bindings, the binding root is the exp
vendor: 16,985 bytes, lines 76617-77072
76617andoStartIndex + 76618 * any directive instances + any hostVars in directives evaluated before it. 76619 * 76620 * See VIEW_DATA.md for more information about host binding resolution. 76621 */ 76622 76623/** 76624 * If the value hasn't been saved, calls the pure function to store and return the 76625 * value. If it has been saved, returns the saved value. 76626 * 76627 * @param slotOffset the offset from binding root to the reserved slot 76628 * @param pureFn Function that returns a value 76629 * @param thisArg Optional calling context of pureFn 76630 * @returns value 76631 * 76632 * @codeGenApi 76633 */ 76634 76635 76636function ɵɵpureFunction0(slotOffset, pureFn, thisArg) { 76637 const bindingIndex = getBindingRoot() + slotOffset; 76638 const lView = getLView(); 76639 return lView[bindingIndex] === NO_CHANGE ? updateBinding(lView, bindingIndex, thisArg ? pureFn.call(thisArg) : pureFn()) : getBinding(lView, bindingIndex); 76640} 76641/** 76642 * If the value of the provided exp has changed, calls the pure function to return 76643 * an updated value. Or if the value has not changed, returns cached value. 76644 * 76645 * @param slotOffset the offset from binding root to the reserved slot 76646 * @param pureFn Function that returns an updated value 76647 * @param exp Updated expression value 76648 * @param thisArg Optional calling context of pureFn 76649 * @returns Updated or cached value 76650 * 76651 * @codeGenApi 76652 */ 76653 76654 76655function ɵɵpureFunction1(slotOffset, pureFn, exp, thisArg) { 76656 return pureFunction1Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp, thisArg); 76657} 76658/** 76659 * If the value of any provided exp has changed, calls the pure function to return 76660 * an updated value. Or if no values have changed, returns cached value. 76661 * 76662 * @param slotOffset the offset from binding root to the reserved slot 76663 * @param pureFn 76664 * @param exp1 76665 * @param exp2 76666 * @param thisArg Optional calling context of pureFn 76667 * @returns Updated or cached value 76668 * 76669 * @codeGenApi 76670 */ 76671 76672 76673function ɵɵpureFunction2(slotOffset, pureFn, exp1, exp2, thisArg) { 76674 return pureFunction2Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, thisArg); 76675} 76676/** 76677 * If the value of any provided exp has changed, calls the pure function to return 76678 * an updated value. Or if no values have changed, returns cached value. 76679 * 76680 * @param slotOffset the offset from binding root to the reserved slot 76681 * @param pureFn 76682 * @param exp1 76683 * @param exp2 76684 * @param exp3 76685 * @param thisArg Optional calling context of pureFn 76686 * @returns Updated or cached value 76687 * 76688 * @codeGenApi 76689 */ 76690 76691 76692function ɵɵpureFunction3(slotOffset, pureFn, exp1, exp2, exp3, thisArg) { 76693 return pureFunction3Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, exp3, thisArg); 76694} 76695/** 76696 * If the value of any provided exp has changed, calls the pure function to return 76697 * an updated value. Or if no values have changed, returns cached value. 76698 * 76699 * @param slotOffset the offset from binding root to the reserved slot 76700 * @param pureFn 76701 * @param exp1 76702 * @param exp2 76703 * @param exp3 76704 * @param exp4 76705 * @param thisArg Optional calling context of pureFn 76706 * @returns Updated or cached value 76707 * 76708 * @codeGenApi 76709 */ 76710 76711 76712function ɵɵpureFunction4(slotOffset, pureFn, exp1, exp2, exp3, exp4, thisArg) { 76713 return pureFunction4Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, exp3, exp4, thisArg); 76714} 76715/** 76716 * If the value of any provided exp has changed, calls the pure function to return 76717 * an updated value. Or if no values have changed, returns cached value. 76718 * 76719 * @param slotOffset the offset from binding root to the reserved slot 76720 * @param pureFn 76721 * @param exp1 76722 * @param exp2 76723 * @param exp3 76724 * @param exp4 76725 * @param exp5 76726 * @param thisArg Optional calling context of pureFn 76727 * @returns Updated or cached value 76728 * 76729 * @codeGenApi 76730 */ 76731 76732 76733function ɵɵpureFunction5(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, thisArg) { 76734 const bindingIndex = getBindingRoot() + slotOffset; 76735 const lView = getLView(); 76736 const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4); 76737 return bindingUpdated(lView, bindingIndex + 4, exp5) || different ? updateBinding(lView, bindingIndex + 5, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5) : pureFn(exp1, exp2, exp3, exp4, exp5)) : getBinding(lView, bindingIndex + 5); 76738} 76739/** 76740 * If the value of any provided exp has changed, calls the pure function to return 76741 * an updated value. Or if no values have changed, returns cached value. 76742 * 76743 * @param slotOffset the offset from binding root to the reserved slot 76744 * @param pureFn 76745 * @param exp1 76746 * @param exp2 76747 * @param exp3 76748 * @param exp4 76749 * @param exp5 76750 * @param exp6 76751 * @param thisArg Optional calling context of pureFn 76752 * @returns Updated or cached value 76753 * 76754 * @codeGenApi 76755 */ 76756 76757 76758function ɵɵpureFunction6(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, exp6, thisArg) { 76759 const bindingIndex = getBindingRoot() + slotOffset; 76760 const lView = getLView(); 76761 const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4); 76762 return bindingUpdated2(lView, bindingIndex + 4, exp5, exp6) || different ? updateBinding(lView, bindingIndex + 6, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6) : pureFn(exp1, exp2, exp3, exp4, exp5, exp6)) : getBinding(lView, bindingIndex + 6); 76763} 76764/** 76765 * If the value of any provided exp has changed, calls the pure function to return 76766 * an updated value. Or if no values have changed, returns cached value. 76767 * 76768 * @param slotOffset the offset from binding root to the reserved slot 76769 * @param pureFn 76770 * @param exp1 76771 * @param exp2 76772 * @param exp3 76773 * @param exp4 76774 * @param exp5 76775 * @param exp6 76776 * @param exp7 76777 * @param thisArg Optional calling context of pureFn 76778 * @returns Updated or cached value 76779 * 76780 * @codeGenApi 76781 */ 76782 76783 76784function ɵɵpureFunction7(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, exp6, exp7, thisArg) { 76785 const bindingIndex = getBindingRoot() + slotOffset; 76786 const lView = getLView(); 76787 let different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4); 76788 return bindingUpdated3(lView, bindingIndex + 4, exp5, exp6, exp7) || different ? updateBinding(lView, bindingIndex + 7, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6, exp7) : pureFn(exp1, exp2, exp3, exp4, exp5, exp6, exp7)) : getBinding(lView, bindingIndex + 7); 76789} 76790/** 76791 * If the value of any provided exp has changed, calls the pure function to return 76792 * an updated value. Or if no values have changed, returns cached value. 76793 * 76794 * @param slotOffset the offset from binding root to the reserved slot 76795 * @param pureFn 76796 * @param exp1 76797 * @param exp2 76798 * @param exp3 76799 * @param exp4 76800 * @param exp5 76801 * @param exp6 76802 * @param exp7 76803 * @param exp8 76804 * @param thisArg Optional calling context of pureFn 76805 * @returns Updated or cached value 76806 * 76807 * @codeGenApi 76808 */ 76809 76810 76811function ɵɵpureFunction8(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8, thisArg) { 76812 const bindingIndex = getBindingRoot() + slotOffset; 76813 const lView = getLView(); 76814 const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4); 76815 return bindingUpdated4(lView, bindingIndex + 4, exp5, exp6, exp7, exp8) || different ? updateBinding(lView, bindingIndex + 8, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8) : pureFn(exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8)) : getBinding(lView, bindingIndex + 8); 76816} 76817/** 76818 * pureFunction instruction that can support any number of bindings. 76819 * 76820 * If the value of any provided exp has changed, calls the pure function to return 76821 * an updated value. Or if no values have changed, returns cached value. 76822 * 76823 * @param slotOffset the offset from binding root to the reserved slot 76824 * @param pureFn A pure function that takes binding values and builds an object or array 76825 * containing those values. 76826 * @param exps An array of binding values 76827 * @param thisArg Optional calling context of pureFn 76828 * @returns Updated or cached value 76829 * 76830 * @codeGenApi 76831 */ 76832 76833 76834function ɵɵpureFunctionV(slotOffset, pureFn, exps, thisArg) { 76835 return pureFunctionVInternal(getLView(), getBindingRoot(), slotOffset, pureFn, exps, thisArg); 76836} 76837/** 76838 * Results of a pure function invocation are stored in LView in a dedicated slot that is initialized 76839 * to NO_CHANGE. In rare situations a pure pipe might throw an exception on the very first 76840 * invocation and not produce any valid results. In this case LView would keep holding the NO_CHANGE 76841 * value. The NO_CHANGE is not something that we can use in expressions / bindings thus we convert 76842 * it to `undefined`. 76843 */ 76844 76845 76846function getPureFunctionReturnValue(lView, returnValueIndex) { 76847 ngDevMode && assertIndexInRange(lView, returnValueIndex); 76848 const lastReturnValue = lView[returnValueIndex]; 76849 return lastReturnValue === NO_CHANGE ? undefined : lastReturnValue; 76850} 76851/** 76852 * If the value of the provided exp has changed, calls the pure function to return 76853 * an updated value. Or if the value has not changed, returns cached value. 76854 * 76855 * @param lView LView in which the function is being executed. 76856 * @param bindingRoot Binding root index. 76857 * @param slotOffset the offset from binding root to the reserved slot 76858 * @param pureFn Function that returns an updated value 76859 * @param exp Updated expression value 76860 * @param thisArg Optional calling context of pureFn 76861 * @returns Updated or cached value 76862 */ 76863 76864 76865function pureFunction1Internal(lView, bindingRoot, slotOffset, pureFn, exp, thisArg) { 76866 const bindingIndex = bindingRoot + slotOffset; 76867 return bindingUpdated(lView, bindingIndex, exp) ? updateBinding(lView, bindingIndex + 1, thisArg ? pureFn.call(thisArg, exp) : pureFn(exp)) : getPureFunctionReturnValue(lView, bindingIndex + 1); 76868} 76869/** 76870 * If the value of any provided exp has changed, calls the pure function to return 76871 * an updated value. Or if no values have changed, returns cached value. 76872 * 76873 * @param lView LView in which the function is being executed. 76874 * @param bindingRoot Binding root index. 76875 * @param slotOffset the offset from binding root to the reserved slot 76876 * @param pureFn 76877 * @param exp1 76878 * @param exp2 76879 * @param thisArg Optional calling context of pureFn 76880 * @returns Updated or cached value 76881 */ 76882 76883 76884function pureFunction2Internal(lView, bindingRoot, slotOffset, pureFn, exp1, exp2, thisArg) { 76885 const bindingIndex = bindingRoot + slotOffset; 76886 return bindingUpdated2(lView, bindingIndex, exp1, exp2) ? updateBinding(lView, bindingIndex + 2, thisArg ? pureFn.call(thisArg, exp1, exp2) : pureFn(exp1, exp2)) : getPureFunctionReturnValue(lView, bindingIndex + 2); 76887} 76888/** 76889 * If the value of any provided exp has changed, calls the pure function to return 76890 * an updated value. Or if no values have changed, returns cached value. 76891 * 76892 * @param lView LView in which the function is being executed. 76893 * @param bindingRoot Binding root index. 76894 * @param slotOffset the offset from binding root to the reserved slot 76895 * @param pureFn 76896 * @param exp1 76897 * @param exp2 76898 * @param exp3 76899 * @param thisArg Optional calling context of pureFn 76900 * @returns Updated or cached value 76901 */ 76902 76903 76904function pureFunction3Internal(lView, bindingRoot, slotOffset, pureFn, exp1, exp2, exp3, thisArg) { 76905 const bindingIndex = bindingRoot + slotOffset; 76906 return bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) ? updateBinding(lView, bindingIndex + 3, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3) : pureFn(exp1, exp2, exp3)) : getPureFunctionReturnValue(lView, bindingIndex + 3); 76907} 76908/** 76909 * If the value of any provided exp has changed, calls the pure function to return 76910 * an updated value. Or if no values have changed, returns cached value. 76911 * 76912 * @param lView LView in which the function is being executed. 76913 * @param bindingRoot Binding root index. 76914 * @param slotOffset the offset from binding root to the reserved slot 76915 * @param pureFn 76916 * @param exp1 76917 * @param exp2 76918 * @param exp3 76919 * @param exp4 76920 * @param thisArg Optional calling context of pureFn 76921 * @returns Updated or cached value 76922 * 76923 */ 76924 76925 76926function pureFunction4Internal(lView, bindingRoot, slotOffset, pureFn, exp1, exp2, exp3, exp4, thisArg) { 76927 const bindingIndex = bindingRoot + slotOffset; 76928 return bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) ? updateBinding(lView, bindingIndex + 4, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4) : pureFn(exp1, exp2, exp3, exp4)) : getPureFunctionReturnValue(lView, bindingIndex + 4); 76929} 76930/** 76931 * pureFunction instruction that can support any number of bindings. 76932 * 76933 * If the value of any provided exp has changed, calls the pure function to return 76934 * an updated value. Or if no values have changed, returns cached value. 76935 * 76936 * @param lView LView in which the function is being executed. 76937 * @param bindingRoot Binding root index. 76938 * @param slotOffset the offset from binding root to the reserved slot 76939 * @param pureFn A pure function that takes binding values and builds an object or array 76940 * containing those values. 76941 * @param exps An array of binding values 76942 * @param thisArg Optional calling context of pureFn 76943 * @returns Updated or cached value 76944 */ 76945 76946 76947function pureFunctionVInternal(lView, bindingRoot, slotOffset, pureFn, exps, thisArg) { 76948 let bindingIndex = bindingRoot + slotOffset; 76949 let different = false; 76950 76951 for (let i = 0; i < exps.length; i++) { 76952 bindingUpdated(lView, bindingIndex++, exps[i]) && (different = true); 76953 } 76954 76955 return different ? updateBinding(lView, bindingIndex, pureFn.apply(thisArg, exps)) : getPureFunctionReturnValue(lView, bindingIndex); 76956} 76957/** 76958 * @license 76959 * Copyright Google LLC All Rights Reserved. 76960 * 76961 * Use of this source code is governed by an MIT-style license that can be 76962 * found in the LICENSE file at https://angular.io/license 76963 */ 76964 76965/** 76966 * Create a pipe. 76967 * 76968 * @param index Pipe index where the pipe will be stored. 76969 * @param pipeName The name of the pipe 76970 * @returns T the instance of the pipe. 76971 * 76972 * @codeGenApi 76973 */ 76974 76975 76976function ɵɵpipe(index, pipeName) { 76977 const tView = getTView(); 76978 let pipeDef; 76979 const adjustedIndex = index + HEADER_OFFSET; 76980 76981 if (tView.firstCreatePass) { 76982 // The `getPipeDef` throws if a pipe with a given name is not found 76983 // (so we use non-null assertion below). 76984 pipeDef = getPipeDef(pipeName, tView.pipeRegistry); 76985 tView.data[adjustedIndex] = pipeDef; 76986 76987 if (pipeDef.onDestroy) { 76988 (tView.destroyHooks || (tView.destroyHooks = [])).push(adjustedIndex, pipeDef.onDestroy); 76989 } 76990 } else { 76991 pipeDef = tView.data[adjustedIndex]; 76992 } 76993 76994 const pipeFactory = pipeDef.factory || (pipeDef.factory = getFactoryDef(pipeDef.type, true)); 76995 const previousInjectImplementation = setInjectImplementation(ɵɵdirectiveInject); 76996 76997 try { 76998 // DI for pipes is supposed to behave like directives when placed on a component 76999 // host node, which means that we have to disable access to `viewProviders`. 77000 const previousIncludeViewProviders = setIncludeViewProviders(false); 77001 const pipeInstance = pipeFactory(); 77002 setIncludeViewProviders(previousIncludeViewProviders); 77003 store(tView, getLView(), adjustedIndex, pipeInstance); 77004 return pipeInstance; 77005 } finally { 77006 // we have to restore the injector implementation in finally, just in case the creation of the 77007 // pipe throws an error. 77008 setInjectImplementation(previousInjectImplementation); 77009 } 77010} 77011/** 77012 * Searches the pipe registry for a pipe with the given name. If one is found, 77013 * returns the pipe. Otherwise, an error is thrown because the pipe cannot be resolved. 77014 * 77015 * @param name Name of pipe to resolve 77016 * @param registry Full list of available pipes 77017 * @returns Matching PipeDef 77018 */ 77019 77020 77021function getPipeDef(name, registry) { 77022 if (registry) { 77023 for (let i = registry.length - 1; i >= 0; i--) { 77024 const pipeDef = registry[i]; 77025 77026 if (name === pipeDef.name) { 77027 return pipeDef; 77028 } 77029 } 77030 } 77031 77032 if (ngDevMode) { 77033 throw new RuntimeError(-302 77034 /* RuntimeErrorCode.PIPE_NOT_FOUND */ 77035 , getPipeNotFoundErrorMessage(name)); 77036 } 77037} 77038/** 77039 * Generates a helpful error message for the user when a pipe is not found. 77040 * 77041 * @param name Name of the missing pipe 77042 * @returns The error message 77043 */ 77044 77045 77046function getPipeNotFoundErrorMessage(name) { 77047 const lView = getLView(); 77048 const declarationLView = lView[DECLARATION_COMPONENT_VIEW]; 77049 const context = declarationLView[CONTEXT]; 77050 const hostIsStandalone = isHostComponentStandalone(lView); 77051 const componentInfoMessage = context ? ` in the '${context.constructor.name}' component` : ''; 77052 const verifyMessage = `Verify that it is ${hostIsStandalone ? 'included in the \'@Component.imports\' of this component' : 'declared or imported in this module'}`; 77053 const errorMessage = `The pipe '${name}' could not be found${componentInfoMessage}. ${verifyMessage}`; 77054 return errorMessage; 77055} 77056/** 77057 * Invokes a pipe with 1 arguments. 77058 * 77059 * This instruction acts as a guard to {@link PipeTransform#transform} invoking 77060 * the pipe only when an input to the pipe changes. 77061 * 77062 * @param index Pipe index where the pipe was stored on creation. 77063 * @param slotOffset the offset in the reserved slot space 77064 * @param v1 1st argument to {@link PipeTransform#transform}. 77065 * 77066 * @codeGenApi 77067 */ 77068 77069 77070function ɵɵpipeBind1(index, slotOffset, v1) { 77071 const adjustedIndex = index + HEADER_OFFSET; 77072 const lView = getLView();
77073 const pipeInstance = load(lView, adjustedIndex); 77074 return isPure(lView, adjustedIndex) ? pureFunction1Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, pipeInstance) : pipeInstance.transform(v1); 77075} 77076/** 77077 * Invokes a pipe with 2 arguments. 77078 * 77079 * This instruction acts as a guard to {@link PipeTransform#transform} invoking 77080 * the pipe only when an input to the pipe changes. 77081 * 77082 * @param index Pipe index where the pipe was stored on creation. 77083 * @param slotOffset the offset in the reserved slot space 77084 * @param v1 1st argument to {@link PipeTransform#transform}. 77085 * @param v2 2nd argument to {@link PipeTransform#transform}. 77086 * 77087 * @codeGenApi 77088 */ 77089 77090 77091function ɵɵpipeBind2(index, slotOffset, v1, v2) { 77092 const adjustedIndex = index + HEADER_OFFSET; 77093 const lView = getLView(); 77094 const pipeInstance = load(lView, adjustedIndex); 77095 return isPure(lView, adjustedIndex) ? pureFunction2Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, pipeInstance) : pipeInstance.transform(v1, v2); 77096} 77097/** 77098 * Invokes a pipe with 3 arguments. 77099 * 77100 * This instruction acts as a guard to {@link PipeTransform#transform} invoking 77101 * the pipe only when an input to the pipe changes. 77102 * 77103 * @param index Pipe index where the pipe was stored on creation. 77104 * @param slotOffset the offset in the reserved slot space 77105 * @param v1 1st argument to {@link PipeTransform#transform}. 77106 * @param v2 2nd argument to {@link PipeTransform#transform}. 77107 * @param v3 4rd argument to {@link PipeTransform#transform}. 77108 * 77109 * @codeGenApi 77110 */ 77111 77112 77113function ɵɵpipeBind3(index, slotOffset, v1, v2, v3) { 77114 const adjustedIndex = index + HEADER_OFFSET; 77115 const lView = getLView(); 77116 const pipeInstance = load(lView, adjustedIndex); 77117 return isPure(lView, adjustedIndex) ? pureFunction3Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, v3, pipeInstance) : pipeInstance.transform(v1, v2, v3); 77118} 77119/** 77120 * Invokes a pipe with 4 arguments. 77121 * 77122 * This instruction acts as a guard to {@link PipeTransform#transform} invoking 77123 * the pipe only when an input to the pipe changes. 77124 * 77125 * @param index Pipe index where the pipe was stored on creation. 77126 * @param slotOffset the offset in the reserved slot space 77127 * @param v1 1st argument to {@link PipeTransform#transform}. 77128 * @param v2 2nd argument to {@link PipeTransform#transform}. 77129 * @param v3 3rd argument to {@link PipeTransform#transform}. 77130 * @param v4 4th argument to {@link PipeTransform#transform}. 77131 * 77132 * @codeGenApi 77133 */ 77134 77135 77136function ɵɵpipeBind4(index, slotOffset, v1, v2, v3, v4) { 77137 const adjustedIndex = index + HEADER_OFFSET; 77138 const lView = getLView(); 77139 const pipeInstance = load(lView, adjustedIndex); 77140 return isPure(lView, adjustedIndex) ? pureFunction4Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, v3, v4, pipeInstance) : pipeInstance.transform(v1, v2, v3, v4); 77141} 77142/** 77143 * Invokes a pipe with variable number of arguments. 77144 * 77145 * This instruction acts as a guard to {@link PipeTransform#transform} invoking 77146 * the pipe only when an input to the pipe changes. 77147 * 77148 * @param index Pipe index where the pipe was stored on creation. 77149 * @param slotOffset the offset in the reserved slot space 77150 * @param values Array of arguments to pass to {@link PipeTransform#transform} method. 77151 * 77152 * @codeGenApi 77153 */ 77154 77155 77156function ɵɵpipeBindV(index, slotOffset, values) { 77157 const adjustedIndex = index + HEADER_OFFSET; 77158 const lView = getLView(); 77159 const pipeInstance = load(lView, adjustedIndex); 77160 return isPure(lView, adjustedIndex) ? pureFunctionVInternal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, values, pipeInstance) : pipeInstance.transform.apply(pipeInstance, values); 77161} 77162 77163function isPure(lView, index) { 77164 return lView[TVIEW].data[index].pure; 77165} 77166/** 77167 * @license 77168 * Copyright Google LLC All Rights Reserved. 77169 * 77170 * Use of this source code is governed by an MIT-style license that can be 77171 * found in the LICENSE file at https://angular.io/license 77172 */ 77173 77174 77175class EventEmitter_ extends rxjs__WEBPACK_IMPORTED_MODULE_0__.Subject { 77176 constructor(isAsync = false) { 77177 super(); 77178 this.__isAsync = isAsync; 77179 } 77180 77181 emit(value) { 77182 super.next(value); 77183 } 77184 77185 subscribe(observerOrNext, error, complete) { 77186 let nextFn = observerOrNext; 77187 77188 let errorFn = error || (() => null); 77189
77190 let completeFn = complete; 77191 77192 if (observerOrNext && typeof observerOrNext === 'object') { 77193 const observer = observerOrNext; 77194 nextFn = observer.next?.bind(observer); 77195 errorFn = observer.error?.bind(observer); 77196 completeFn = observer.complete?.bind(observer); 77197 } 77198 77199 if (this.__isAsync) { 77200 errorFn = _wrapInTimeout(errorFn); 77201 77202 if (nextFn) { 77203 nextFn = _wrapInTimeout(nextFn); 77204 } 77205 77206 if (completeFn) { 77207 completeFn = _wrapInTimeout(completeFn); 77208 } 77209 } 77210 77211 const sink = super.subscribe({ 77212 next: nextFn, 77213 error: errorFn, 77214 complete: completeFn 77215 }); 77216 77217 if (observerOrNext instanceof rxjs__WEBPACK_IMPORTED_MODULE_1__.Subscription) { 77218 observerOrNext.add(sink); 77219 } 77220 77221 return sink; 77222 } 77223 77224} 77225 77226function _wrapInTimeout(fn) { 77227 return value => { 77228 setTimeout(fn, undefined, value); 77229 }; 77230} 77231/** 77232 * @publicApi 77233 */ 77234 77235 77236const EventEmitter = EventEmitter_; 77237/** 77238 * @license 77239 * Copyright Google LLC All Rights Reserved. 77240 * 77241 * Use of this source code is governed by an MIT-style license that can be 77242 * found in the LICENSE file at https://angular.io/license 77243 */ 77244 77245function symbolIterator() { 77246 return this._results[getSymbolIterator()](); 77247} 77248/** 77249 * An unmodifiable list of items that Angular keeps up to date when the state 77250 * of the application changes. 77251 * 77252 * The type of object that {@link ViewChildren}, {@link ContentChildren}, and {@link QueryList} 77253 * provide. 77254 * 77255 * Implements an iterable interface, therefore it can be used in both ES6 77256 * javascript `for (var i of items)` loops as well as in Angular templates with 77257 * `*ngFor="let i of myList"`. 77258 * 77259 * Changes can be observed by subscribing to the changes `Observable`. 77260 * 77261 * NOTE: In the future this class will implement an `Observable` interface. 77262 * 77263 * @usageNotes 77264 * ### Example 77265 * ```typescript 77266 * @Component({...}) 77267 * class Container { 77268 * @ViewChildren(Item) items:QueryList<Item>; 77269 * } 77270 * ``` 77271 * 77272 * @publicApi 77273 */ 77274 77275 77276class QueryList { 77277 /** 77278 * @param emitDistinctChangesOnly Whether `QueryList.changes` should fire only when actual change 77279 * has occurred. Or if it should fire when query is recomputed. (recomputing could resolve in 77280 * the same result) 77281 */ 77282 constructor(_emitDistinctChangesOnly = false) { 77283 this._emitDistinctChangesOnly = _emitDistinctChangesOnly; 77284 this.dirty = true; 77285 this._results = []; 77286 this._changesDetected = false; 77287 this._changes = null; 77288 this.length = 0; 77289 this.first = undefined; 77290 this.last = undefined; // This function should be declared on the prototype, but doing so there will cause the class 77291 // declaration to have side-effects and become not tree-shakable. For this reason we do it in 77292 // the constructor. 77293 // [getSymbolIterator()](): Iterator<T> { ... } 77294 77295 const symbol = getSymbolIterator(); 77296 const proto = QueryList.prototype; 77297 if (!proto[symbol]) proto[symbol] = symbolIterator; 77298 } 77299 /** 77300 * Returns `Observable` of `QueryList` notifying the subscriber of changes. 77301 */ 77302 77303 77304 get changes() { 77305 return this._changes || (this._changes = new EventEmitter()); 77306 } 77307 /** 77308 * Returns the QueryList entry at `index`. 77309 */ 77310 77311 77312 get(index) { 77313 return this._results[index]; 77314 } 77315 /** 77316 * See 77317 * [Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) 77318 */ 77319 77320 77321 map(fn) { 77322 return this._results.map(fn); 77323 } 77324 /** 77325 * See 77326 * [Array.filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) 77327 */ 77328 77329 77330 filter(fn) { 77331 return this._results.filter(fn); 77332 } 77333 /** 77334 * See 77335 * [Array.find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find) 77336 */ 77337 77338 77339 find(fn) { 77340 return this._results.find(fn); 77341 } 77342 /** 77343 * See 77344 * [Array.reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) 77345 */ 77346 77347 77348 reduce(fn, init) { 77349 return this._results.reduce(fn, init); 77350 } 77351 /** 77352 * See 77353 * [Array.forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) 77354 */ 77355 77356 77357 forEach(fn) {
77358 this._results.forEach(fn); 77359 } 77360 /** 77361 * See 77362 * [Array.some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some) 77363 */ 77364 77365 77366 some(fn) { 77367 return this._results.some(fn); 77368 } 77369 /** 77370 * Returns a copy of the internal results list as an Array. 77371 */ 77372 77373 77374 toArray() { 77375 return this._results.slice(); 77376 } 77377 77378 toString() { 77379 return this._results.toString(); 77380 } 77381 /** 77382 * Updates the stored data of the query list, and resets the `dirty` flag to `false`, so that 77383 * on change detection, it will not notify of changes to the queries, unless a new change 77384 * occurs. 77385 * 77386 * @param resultsTree The query results to store 77387 * @param identityAccessor Optional function for extracting stable object identity from a value 77388 * in the array. This function is executed for each element of the query result list while 77389 * comparing current query list with the new one (provided as a first argument of the `reset` 77390 * function) to detect if the lists are different. If the function is not provided, elements 77391 * are compared as is (without any pre-processing). 77392 */ 77393 77394 77395 reset(resultsTree, identityAccessor) { 77396 // Cast to `QueryListInternal` so that we can mutate fields which are readonly for the usage of 77397 // QueryList (but not for QueryList itself.) 77398 const self = this; 77399 self.dirty = false; 77400 const newResultFlat = flatten(resultsTree); 77401 77402 if (this._changesDetected = !arrayEquals(self._results, newResultFlat, identityAccessor)) { 77403 self._results = newResultFlat; 77404 self.length = newResultFlat.length; 77405 self.last = newResultFlat[this.length - 1]; 77406 self.first = newResultFlat[0]; 77407 } 77408 } 77409 /** 77410 * Triggers a change event by emitting on the `changes` {@link EventEmitter}. 77411 */ 77412 77413 77414 notifyOnChanges() { 77415 if (this._changes && (this._changesDetected || !this._emitDistinctChangesOnly)) this._changes.emit(this); 77416 } 77417 /** internal */ 77418 77419 77420 setDirty() { 77421 this.dirty = true; 77422 } 77423 /** internal */ 77424 77425 77426 destroy() { 77427 this.changes.complete(); 77428 this.changes.unsubscribe(); 77429 } 77430 77431} 77432 77433Symbol.iterator; 77434/** 77435 * @license 77436 * Copyright Google LLC All Rights Reserved. 77437 * 77438 * Use of this source code is governed by an MIT-style license that can be 77439 * found in the LICENSE file at https://angular.io/license 77440 */ 77441 77442/** 77443 * Represents an embedded template that can be used to instantiate embedded views. 77444 * To instantiate embedded views based on a template, use the `ViewContainerRef` 77445 * method `createEmbeddedView()`. 77446 * 77447 * Access a `TemplateRef` instance by placing a directive on an `<ng-template>` 77448 * element (or directive prefixed with `*`). The `TemplateRef` for the embedded view 77449 * is injected into the constructor of the directive, 77450 * using the `TemplateRef` token. 77451 * 77452 * You can also use a `Query` to find a `TemplateRef` associated with 77453 * a component or a directive. 77454 * 77455 * @see `ViewContainerRef` 77456 * @see [Navigate the Component Tree with DI](guide/dependency-injection-navtree) 77457 * 77458 * @publicApi 77459 */ 77460 77461class TemplateRef {} 77462/** 77463 * @internal 77464 * @nocollapse 77465 */ 77466 77467 77468TemplateRef.__NG_ELEMENT_ID__ = injectTemplateRef; 77469const ViewEngineTemplateRef = TemplateRef; // TODO(alxhub): combine interface and implementation. Currently this is challenging since something 77470// in g3 depends on them being separate. 77471 77472const R3TemplateRef = class TemplateRef extends ViewEngineTemplateRef { 77473 constructor(_declarationLView, _declarationTContainer, elementRef) { 77474 super(); 77475 this._declarationLView = _declarationLView; 77476 this._declarationTContainer = _declarationTContainer; 77477 this.elementRef = elementRef; 77478 } 77479 77480 createEmbeddedView(context, injector) { 77481 const embeddedTView = this._declarationTContainer.tViews; 77482 const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16 77483 /* LViewFlags.CheckAlways */ 77484 , null, embeddedTView.declTNode, null, null, null, null, injector || null); 77485 const declarationLContainer = this._declarationLView[this._declarationTContainer.index]; 77486 ngDevMode && assertLContainer(declarationLContainer); 77487 embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer; 77488 const declarationViewLQueries = this._declarationLView[QUERIES]; 77489 77490 if (declarationViewLQueries !== null) { 77491 embeddedLView[QUERIES] = declarationViewLQueries.createEmbeddedView(embeddedTView); 77492 } 77493 77494 renderView(embeddedTView, embeddedLView, context); 77495 return new ViewRef$1(embeddedLView); 77496 } 77497 77498}; 77499/**
vendor: 31,862 bytes, lines 77500-78446
77500 * Creates a TemplateRef given a node. 77501 * 77502 * @returns The TemplateRef instance to use 77503 */ 77504 77505function injectTemplateRef() { 77506 return createTemplateRef(getCurrentTNode(), getLView()); 77507} 77508/** 77509 * Creates a TemplateRef and stores it on the injector. 77510 * 77511 * @param hostTNode The node on which a TemplateRef is requested 77512 * @param hostLView The `LView` to which the node belongs 77513 * @returns The TemplateRef instance or null if we can't create a TemplateRef on a given node type 77514 */ 77515 77516 77517function createTemplateRef(hostTNode, hostLView) { 77518 if (hostTNode.type & 4 77519 /* TNodeType.Container */ 77520 ) { 77521 ngDevMode && assertDefined(hostTNode.tViews, 'TView must be allocated'); 77522 return new R3TemplateRef(hostLView, hostTNode, createElementRef(hostTNode, hostLView)); 77523 } 77524 77525 return null; 77526} 77527/** 77528 * @license 77529 * Copyright Google LLC All Rights Reserved. 77530 * 77531 * Use of this source code is governed by an MIT-style license that can be 77532 * found in the LICENSE file at https://angular.io/license 77533 */ 77534 77535/** 77536 * Represents a container where one or more views can be attached to a component. 77537 * 77538 * Can contain *host views* (created by instantiating a 77539 * component with the `createComponent()` method), and *embedded views* 77540 * (created by instantiating a `TemplateRef` with the `createEmbeddedView()` method). 77541 * 77542 * A view container instance can contain other view containers, 77543 * creating a [view hierarchy](guide/glossary#view-tree). 77544 * 77545 * @see `ComponentRef` 77546 * @see `EmbeddedViewRef` 77547 * 77548 * @publicApi 77549 */ 77550 77551 77552class ViewContainerRef {} 77553/** 77554 * @internal 77555 * @nocollapse 77556 */ 77557 77558 77559ViewContainerRef.__NG_ELEMENT_ID__ = injectViewContainerRef; 77560/** 77561 * Creates a ViewContainerRef and stores it on the injector. Or, if the ViewContainerRef 77562 * already exists, retrieves the existing ViewContainerRef. 77563 * 77564 * @returns The ViewContainerRef instance to use 77565 */ 77566 77567function injectViewContainerRef() { 77568 const previousTNode = getCurrentTNode(); 77569 return createContainerRef(previousTNode, getLView()); 77570} 77571 77572const VE_ViewContainerRef = ViewContainerRef; // TODO(alxhub): cleaning up this indirection triggers a subtle bug in Closure in g3. Once the fix 77573// for that lands, this can be cleaned up. 77574 77575const R3ViewContainerRef = class ViewContainerRef extends VE_ViewContainerRef { 77576 constructor(_lContainer, _hostTNode, _hostLView) { 77577 super(); 77578 this._lContainer = _lContainer; 77579 this._hostTNode = _hostTNode; 77580 this._hostLView = _hostLView; 77581 } 77582 77583 get element() { 77584 return createElementRef(this._hostTNode, this._hostLView); 77585 } 77586 77587 get injector() { 77588 return new NodeInjector(this._hostTNode, this._hostLView); 77589 } 77590 /** @deprecated No replacement */ 77591 77592 77593 get parentInjector() { 77594 const parentLocation = getParentInjectorLocation(this._hostTNode, this._hostLView); 77595 77596 if (hasParentInjector(parentLocation)) { 77597 const parentView = getParentInjectorView(parentLocation, this._hostLView); 77598 const injectorIndex = getParentInjectorIndex(parentLocation); 77599 ngDevMode && assertNodeInjector(parentView, injectorIndex); 77600 const parentTNode = parentView[TVIEW].data[injectorIndex + 8 77601 /* NodeInjectorOffset.TNODE */ 77602 ]; 77603 return new NodeInjector(parentTNode, parentView); 77604 } else { 77605 return new NodeInjector(null, this._hostLView); 77606 } 77607 } 77608 77609 clear() { 77610 while (this.length > 0) { 77611 this.remove(this.length - 1); 77612 } 77613 } 77614 77615 get(index) { 77616 const viewRefs = getViewRefs(this._lContainer); 77617 return viewRefs !== null && viewRefs[index] || null; 77618 } 77619 77620 get length() { 77621 return this._lContainer.length - CONTAINER_HEADER_OFFSET; 77622 } 77623 77624 createEmbeddedView(templateRef, context, indexOrOptions) { 77625 let index; 77626 let injector; 77627 77628 if (typeof indexOrOptions === 'number') { 77629 index = indexOrOptions; 77630 } else if (indexOrOptions != null) { 77631 index = indexOrOptions.index; 77632 injector = indexOrOptions.injector; 77633 } 77634 77635 const viewRef = templateRef.createEmbeddedView(context || {}, injector); 77636 this.insert(viewRef, index); 77637 return viewRef; 77638 } 77639 77640 createComponent(componentFactoryOrType, indexOrOptions, injector, projectableNodes, environmentInjector) { 77641 const isComponentFactory = componentFactoryOrType && !isType(componentFactoryOrType); 77642 let index; // This function supports 2 signatures and we need to handle options correctly for both: 77643 // 1. When first argument is a Component type. This signature also requires extra 77644 // options to be provided as as object (more ergonomic option). 77645 // 2. First argument is a Component factory. In this case extra options are represented as 77646 // positional arguments. This signature is less ergonomic and will be deprecated. 77647 77648 if (isComponentFactory) { 77649 if (ngDevMode) { 77650 assertEqual(typeof indexOrOptions !== 'object', true, 'It looks like Component factory was provided as the first argument ' + 'and an options object as the second argument. This combination of arguments ' + 'is incompatible. You can either change the first argument to provide Component ' + 'type or change the second argument to be a number (representing an index at ' + 'which to insert the new component\'s host view into this container)'); 77651 } 77652 77653 index = indexOrOptions; 77654 } else { 77655 if (ngDevMode) { 77656 assertDefined(getComponentDef(componentFactoryOrType), `Provided Component class doesn't contain Component definition. ` + `Please check whether provided class has @Component decorator.`); 77657 assertEqual(typeof indexOrOptions !== 'number', true, 'It looks like Component type was provided as the first argument ' + 'and a number (representing an index at which to insert the new component\'s ' + 'host view into this container as the second argument. This combination of arguments ' + 'is incompatible. Please use an object as the second argument instead.'); 77658 } 77659 77660 const options = indexOrOptions || {}; 77661 77662 if (ngDevMode && options.environmentInjector && options.ngModuleRef) { 77663 throwError(`Cannot pass both environmentInjector and ngModuleRef options to createComponent().`); 77664 } 77665 77666 index = options.index; 77667 injector = options.injector; 77668 projectableNodes = options.projectableNodes; 77669 environmentInjector = options.environmentInjector || options.ngModuleRef; 77670 } 77671 77672 const componentFactory = isComponentFactory ? componentFactoryOrType : new ComponentFactory(getComponentDef(componentFactoryOrType)); 77673 const contextInjector = injector || this.parentInjector; // If an `NgModuleRef` is not provided explicitly, try retrieving it from the DI tree. 77674 77675 if (!environmentInjector && componentFactory.ngModule == null) { 77676 // For the `ComponentFactory` case, entering this logic is very unlikely, since we expect that 77677 // an instance of a `ComponentFactory`, resolved via `ComponentFactoryResolver` would have an 77678 // `ngModule` field. This is possible in some test scenarios and potentially in some JIT-based 77679 // use-cases. For the `ComponentFactory` case we preserve backwards-compatibility and try 77680 // using a provided injector first, then fall back to the parent injector of this 77681 // `ViewContainerRef` instance. 77682 // 77683 // For the factory-less case, it's critical to establish a connection with the module 77684 // injector tree (by retrieving an instance of an `NgModuleRef` and accessing its injector), 77685 // so that a component can use DI tokens provided in MgModules. For this reason, we can not 77686 // rely on the provided injector, since it might be detached from the DI tree (for example, if 77687 // it was created via `Injector.create` without specifying a parent injector, or if an 77688 // injector is retrieved from an `NgModuleRef` created via `createNgModule` using an 77689 // NgModule outside of a module tree). Instead, we always use `ViewContainerRef`'s parent 77690 // injector, which is normally connected to the DI tree, which includes module injector 77691 // subtree. 77692 const _injector = isComponentFactory ? contextInjector : this.parentInjector; // DO NOT REFACTOR. The code here used to have a `injector.get(NgModuleRef, null) || 77693 // undefined` expression which seems to cause internal google apps to fail. This is documented 77694 // in the following internal bug issue: go/b/142967802 77695 77696 77697 const result = _injector.get(EnvironmentInjector, null); 77698 77699 if (result) { 77700 environmentInjector = result; 77701 } 77702 } 77703 77704 const componentRef = componentFactory.create(contextInjector, projectableNodes, undefined, environmentInjector); 77705 this.insert(componentRef.hostView, index); 77706 return componentRef; 77707 } 77708 77709 insert(viewRef, index) { 77710 const lView = viewRef._lView; 77711 const tView = lView[TVIEW]; 77712 77713 if (ngDevMode && viewRef.destroyed) { 77714 throw new Error('Cannot insert a destroyed View in a ViewContainer!'); 77715 } 77716 77717 if (viewAttachedToContainer(lView)) { 77718 // If view is already attached, detach it first so we clean up references appropriately. 77719 const prevIdx = this.indexOf(viewRef); // A view might be attached either to this or a different container. The `prevIdx` for 77720 // those cases will be: 77721 // equal to -1 for views attached to this ViewContainerRef 77722 // >= 0 for views attached to a different ViewContainerRef 77723 77724 if (prevIdx !== -1) { 77725 this.detach(prevIdx); 77726 } else { 77727 const prevLContainer = lView[PARENT]; 77728 ngDevMode && assertEqual(isLContainer(prevLContainer), true, 'An attached view should have its PARENT point to a container.'); // We need to re-create a R3ViewContainerRef instance since those are not stored on 77729 // LView (nor anywhere else). 77730 77731 const prevVCRef = new R3ViewContainerRef(prevLContainer, prevLContainer[T_HOST], prevLContainer[PARENT]); 77732 prevVCRef.detach(prevVCRef.indexOf(viewRef)); 77733 } 77734 } // Logical operation of adding `LView` to `LContainer` 77735 77736 77737 const adjustedIdx = this._adjustIndex(index); 77738 77739 const lContainer = this._lContainer; 77740 insertView(tView, lView, lContainer, adjustedIdx); // Physical operation of adding the DOM nodes. 77741 77742 const beforeNode = getBeforeNodeForView(adjustedIdx, lContainer); 77743 const renderer = lView[RENDERER]; 77744 const parentRNode = nativeParentNode(renderer, lContainer[NATIVE]); 77745 77746 if (parentRNode !== null) { 77747 addViewToContainer(tView, lContainer[T_HOST], renderer, lView, parentRNode, beforeNode); 77748 } 77749 77750 viewRef.attachToViewContainerRef(); 77751 addToArray(getOrCreateViewRefs(lContainer), adjustedIdx, viewRef); 77752 return viewRef; 77753 } 77754 77755 move(viewRef, newIndex) { 77756 if (ngDevMode && viewRef.destroyed) { 77757 throw new Error('Cannot move a destroyed View in a ViewContainer!'); 77758 } 77759 77760 return this.insert(viewRef, newIndex); 77761 } 77762 77763 indexOf(viewRef) { 77764 const viewRefsArr = getViewRefs(this._lContainer); 77765 return viewRefsArr !== null ? viewRefsArr.indexOf(viewRef) : -1; 77766 } 77767 77768 remove(index) { 77769 const adjustedIdx = this._adjustIndex(index, -1); 77770 77771 const detachedView = detachView(this._lContainer, adjustedIdx); 77772 77773 if (detachedView) { 77774 // Before destroying the view, remove it from the container's array of `ViewRef`s. 77775 // This ensures the view container length is updated before calling 77776 // `destroyLView`, which could recursively call view container methods that 77777 // rely on an accurate container length. 77778 // (e.g. a method on this view container being called by a child directive's OnDestroy 77779 // lifecycle hook) 77780 removeFromArray(getOrCreateViewRefs(this._lContainer), adjustedIdx); 77781 destroyLView(detachedView[TVIEW], detachedView); 77782 } 77783 } 77784 77785 detach(index) { 77786 const adjustedIdx = this._adjustIndex(index, -1); 77787 77788 const view = detachView(this._lContainer, adjustedIdx); 77789 const wasDetached = view && removeFromArray(getOrCreateViewRefs(this._lContainer), adjustedIdx) != null; 77790 return wasDetached ? new ViewRef$1(view) : null; 77791 } 77792 77793 _adjustIndex(index, shift = 0) { 77794 if (index == null) { 77795 return this.length + shift; 77796 } 77797 77798 if (ngDevMode) { 77799 assertGreaterThan(index, -1, `ViewRef index must be positive, got ${index}`); // +1 because it's legal to insert at the end. 77800 77801 assertLessThan(index, this.length + 1 + shift, 'index'); 77802 } 77803 77804 return index; 77805 } 77806 77807}; 77808 77809function getViewRefs(lContainer) { 77810 return lContainer[VIEW_REFS]; 77811} 77812 77813function getOrCreateViewRefs(lContainer) { 77814 return lContainer[VIEW_REFS] || (lContainer[VIEW_REFS] = []); 77815} 77816/** 77817 * Creates a ViewContainerRef and stores it on the injector. 77818 * 77819 * @param ViewContainerRefToken The ViewContainerRef type 77820 * @param ElementRefToken The ElementRef type 77821 * @param hostTNode The node that is requesting a ViewContainerRef 77822 * @param hostLView The view to which the node belongs 77823 * @returns The ViewContainerRef instance to use 77824 */ 77825 77826 77827function createContainerRef(hostTNode, hostLView) { 77828 ngDevMode && assertTNodeType(hostTNode, 12 77829 /* TNodeType.AnyContainer */ 77830 | 3 77831 /* TNodeType.AnyRNode */ 77832 ); 77833 let lContainer; 77834 const slotValue = hostLView[hostTNode.index]; 77835 77836 if (isLContainer(slotValue)) { 77837 // If the host is a container, we don't need to create a new LContainer 77838 lContainer = slotValue; 77839 } else { 77840 let commentNode; // If the host is an element container, the native host element is guaranteed to be a 77841 // comment and we can reuse that comment as anchor element for the new LContainer. 77842 // The comment node in question is already part of the DOM structure so we don't need to append 77843 // it again. 77844 77845 if (hostTNode.type & 8 77846 /* TNodeType.ElementContainer */ 77847 ) { 77848 commentNode = unwrapRNode(slotValue); 77849 } else { 77850 // If the host is a regular element, we have to insert a comment node manually which will 77851 // be used as an anchor when inserting elements. In this specific case we use low-level DOM 77852 // manipulation to insert it. 77853 const renderer = hostLView[RENDERER]; 77854 ngDevMode && ngDevMode.rendererCreateComment++; 77855 commentNode = renderer.createComment(ngDevMode ? 'container' : ''); 77856 const hostNative = getNativeByTNode(hostTNode, hostLView); 77857 const parentOfHostNative = nativeParentNode(renderer, hostNative); 77858 nativeInsertBefore(renderer, parentOfHostNative, commentNode, nativeNextSibling(renderer, hostNative), false); 77859 } 77860 77861 hostLView[hostTNode.index] = lContainer = createLContainer(slotValue, hostLView, commentNode, hostTNode); 77862 addToViewTree(hostLView, lContainer); 77863 } 77864 77865 return new R3ViewContainerRef(lContainer, hostTNode, hostLView); 77866} 77867/** 77868 * @license 77869 * Copyright Google LLC All Rights Reserved. 77870 * 77871 * Use of this source code is governed by an MIT-style license that can be 77872 * found in the LICENSE file at https://angular.io/license 77873 */ 77874// Note: This hack is necessary so we don't erroneously get a circular dependency 77875// failure based on types. 77876 77877 77878const unusedValueExportToPlacateAjd$1 = 1; 77879/** 77880 * @license 77881 * Copyright Google LLC All Rights Reserved. 77882 * 77883 * Use of this source code is governed by an MIT-style license that can be 77884 * found in the LICENSE file at https://angular.io/license 77885 */ 77886// Note: This hack is necessary so we don't erroneously get a circular dependency 77887// failure based on types. 77888 77889const unusedValueExportToPlacateAjd = 1; 77890/** 77891 * @license 77892 * Copyright Google LLC All Rights Reserved. 77893 * 77894 * Use of this source code is governed by an MIT-style license that can be 77895 * found in the LICENSE file at https://angular.io/license 77896 */ 77897 77898const unusedValueToPlacateAjd = unusedValueExportToPlacateAjd$1 + unusedValueExportToPlacateAjd$6 + unusedValueExportToPlacateAjd$5 + unusedValueExportToPlacateAjd; 77899 77900class LQuery_ { 77901 constructor(queryList) { 77902 this.queryList = queryList; 77903 this.matches = null; 77904 } 77905 77906 clone() { 77907 return new LQuery_(this.queryList); 77908 } 77909 77910 setDirty() { 77911 this.queryList.setDirty(); 77912 } 77913 77914} 77915 77916class LQueries_ { 77917 constructor(queries = []) { 77918 this.queries = queries; 77919 } 77920 77921 createEmbeddedView(tView) { 77922 const tQueries = tView.queries; 77923 77924 if (tQueries !== null) { 77925 const noOfInheritedQueries = tView.contentQueries !== null ? tView.contentQueries[0] : tQueries.length; 77926 const viewLQueries = []; // An embedded view has queries propagated from a declaration view at the beginning of the 77927 // TQueries collection and up until a first content query declared in the embedded view. Only 77928 // propagated LQueries are created at this point (LQuery corresponding to declared content 77929 // queries will be instantiated from the content query instructions for each directive). 77930 77931 for (let i = 0; i < noOfInheritedQueries; i++) { 77932 const tQuery = tQueries.getByIndex(i); 77933 const parentLQuery = this.queries[tQuery.indexInDeclarationView]; 77934 viewLQueries.push(parentLQuery.clone()); 77935 } 77936 77937 return new LQueries_(viewLQueries); 77938 } 77939 77940 return null; 77941 } 77942 77943 insertView(tView) { 77944 this.dirtyQueriesWithMatches(tView); 77945 } 77946 77947 detachView(tView) { 77948 this.dirtyQueriesWithMatches(tView); 77949 } 77950 77951 dirtyQueriesWithMatches(tView) { 77952 for (let i = 0; i < this.queries.length; i++) { 77953 if (getTQuery(tView, i).matches !== null) { 77954 this.queries[i].setDirty(); 77955 } 77956 } 77957 } 77958 77959} 77960 77961class TQueryMetadata_ { 77962 constructor(predicate, flags, read = null) { 77963 this.predicate = predicate; 77964 this.flags = flags; 77965 this.read = read; 77966 } 77967 77968} 77969 77970class TQueries_ { 77971 constructor(queries = []) { 77972 this.queries = queries; 77973 } 77974 77975 elementStart(tView, tNode) { 77976 ngDevMode && assertFirstCreatePass(tView, 'Queries should collect results on the first template pass only'); 77977 77978 for (let i = 0; i < this.queries.length; i++) { 77979 this.queries[i].elementStart(tView, tNode); 77980 } 77981 } 77982 77983 elementEnd(tNode) { 77984 for (let i = 0; i < this.queries.length; i++) { 77985 this.queries[i].elementEnd(tNode); 77986 } 77987 } 77988 77989 embeddedTView(tNode) { 77990 let queriesForTemplateRef = null; 77991 77992 for (let i = 0; i < this.length; i++) { 77993 const childQueryIndex = queriesForTemplateRef !== null ? queriesForTemplateRef.length : 0; 77994 const tqueryClone = this.getByIndex(i).embeddedTView(tNode, childQueryIndex); 77995 77996 if (tqueryClone) { 77997 tqueryClone.indexInDeclarationView = i; 77998 77999 if (queriesForTemplateRef !== null) { 78000 queriesForTemplateRef.push(tqueryClone); 78001 } else { 78002 queriesForTemplateRef = [tqueryClone]; 78003 } 78004 } 78005 } 78006 78007 return queriesForTemplateRef !== null ? new TQueries_(queriesForTemplateRef) : null; 78008 } 78009 78010 template(tView, tNode) { 78011 ngDevMode && assertFirstCreatePass(tView, 'Queries should collect results on the first template pass only'); 78012 78013 for (let i = 0; i < this.queries.length; i++) { 78014 this.queries[i].template(tView, tNode); 78015 } 78016 } 78017 78018 getByIndex(index) { 78019 ngDevMode && assertIndexInRange(this.queries, index); 78020 return this.queries[index]; 78021 } 78022 78023 get length() { 78024 return this.queries.length; 78025 } 78026 78027 track(tquery) { 78028 this.queries.push(tquery); 78029 } 78030 78031} 78032 78033class TQuery_ { 78034 constructor(metadata, nodeIndex = -1) { 78035 this.metadata = metadata; 78036 this.matches = null; 78037 this.indexInDeclarationView = -1; 78038 this.crossesNgTemplate = false; 78039 /** 78040 * A flag indicating if a given query still applies to nodes it is crossing. We use this flag 78041 * (alongside with _declarationNodeIndex) to know when to stop applying content queries to 78042 * elements in a template. 78043 */ 78044 78045 this._appliesToNextNode = true; 78046 this._declarationNodeIndex = nodeIndex; 78047 } 78048 78049 elementStart(tView, tNode) { 78050 if (this.isApplyingToNode(tNode)) { 78051 this.matchTNode(tView, tNode); 78052 } 78053 } 78054 78055 elementEnd(tNode) { 78056 if (this._declarationNodeIndex === tNode.index) { 78057 this._appliesToNextNode = false; 78058 } 78059 } 78060 78061 template(tView, tNode) { 78062 this.elementStart(tView, tNode); 78063 } 78064 78065 embeddedTView(tNode, childQueryIndex) { 78066 if (this.isApplyingToNode(tNode)) { 78067 this.crossesNgTemplate = true; // A marker indicating a `<ng-template>` element (a placeholder for query results from 78068 // embedded views created based on this `<ng-template>`). 78069 78070 this.addMatch(-tNode.index, childQueryIndex); 78071 return new TQuery_(this.metadata); 78072 } 78073 78074 return null; 78075 } 78076 78077 isApplyingToNode(tNode) { 78078 if (this._appliesToNextNode && (this.metadata.flags & 1 78079 /* QueryFlags.descendants */ 78080 ) !== 1 78081 /* QueryFlags.descendants */ 78082 ) { 78083 const declarationNodeIdx = this._declarationNodeIndex; 78084 let parent = tNode.parent; // Determine if a given TNode is a "direct" child of a node on which a content query was 78085 // declared (only direct children of query's host node can match with the descendants: false 78086 // option). There are 3 main use-case / conditions to consider here: 78087 // - <needs-target><i #target></i></needs-target>: here <i #target> parent node is a query 78088 // host node; 78089 // - <needs-target><ng-template [ngIf]="true"><i #target></i></ng-template></needs-target>: 78090 // here <i #target> parent node is null; 78091 // - <needs-target><ng-container><i #target></i></ng-container></needs-target>: here we need 78092 // to go past `<ng-container>` to determine <i #target> parent node (but we shouldn't traverse 78093 // up past the query's host node!). 78094 78095 while (parent !== null && parent.type & 8 78096 /* TNodeType.ElementContainer */ 78097 && parent.index !== declarationNodeIdx) { 78098 parent = parent.parent; 78099 } 78100 78101 return declarationNodeIdx === (parent !== null ? parent.index : -1); 78102 } 78103 78104 return this._appliesToNextNode; 78105 } 78106 78107 matchTNode(tView, tNode) { 78108 const predicate = this.metadata.predicate; 78109 78110 if (Array.isArray(predicate)) { 78111 for (let i = 0; i < predicate.length; i++) { 78112 const name = predicate[i]; 78113 this.matchTNodeWithReadOption(tView, tNode, getIdxOfMatchingSelector(tNode, name)); // Also try matching the name to a provider since strings can be used as DI tokens too. 78114 78115 this.matchTNodeWithReadOption(tView, tNode, locateDirectiveOrProvider(tNode, tView, name, false, false)); 78116 } 78117 } else { 78118 if (predicate === TemplateRef) { 78119 if (tNode.type & 4 78120 /* TNodeType.Container */ 78121 ) { 78122 this.matchTNodeWithReadOption(tView, tNode, -1); 78123 } 78124 } else { 78125 this.matchTNodeWithReadOption(tView, tNode, locateDirectiveOrProvider(tNode, tView, predicate, false, false)); 78126 } 78127 } 78128 } 78129 78130 matchTNodeWithReadOption(tView, tNode, nodeMatchIdx) { 78131 if (nodeMatchIdx !== null) { 78132 const read = this.metadata.read; 78133 78134 if (read !== null) { 78135 if (read === ElementRef || read === ViewContainerRef || read === TemplateRef && tNode.type & 4 78136 /* TNodeType.Container */ 78137 ) { 78138 this.addMatch(tNode.index, -2); 78139 } else { 78140 const directiveOrProviderIdx = locateDirectiveOrProvider(tNode, tView, read, false, false); 78141 78142 if (directiveOrProviderIdx !== null) { 78143 this.addMatch(tNode.index, directiveOrProviderIdx); 78144 } 78145 } 78146 } else { 78147 this.addMatch(tNode.index, nodeMatchIdx); 78148 } 78149 } 78150 } 78151 78152 addMatch(tNodeIdx, matchIdx) { 78153 if (this.matches === null) { 78154 this.matches = [tNodeIdx, matchIdx]; 78155 } else { 78156 this.matches.push(tNodeIdx, matchIdx); 78157 } 78158 } 78159 78160} 78161/** 78162 * Iterates over local names for a given node and returns directive index 78163 * (or -1 if a local name points to an element). 78164 * 78165 * @param tNode static data of a node to check 78166 * @param selector selector to match 78167 * @returns directive index, -1 or null if a selector didn't match any of the local names 78168 */ 78169 78170 78171function getIdxOfMatchingSelector(tNode, selector) { 78172 const localNames = tNode.localNames; 78173 78174 if (localNames !== null) { 78175 for (let i = 0; i < localNames.length; i += 2) { 78176 if (localNames[i] === selector) { 78177 return localNames[i + 1]; 78178 } 78179 } 78180 } 78181 78182 return null; 78183} 78184 78185function createResultByTNodeType(tNode, currentView) { 78186 if (tNode.type & (3 78187 /* TNodeType.AnyRNode */ 78188 | 8 78189 /* TNodeType.ElementContainer */ 78190 )) { 78191 return createElementRef(tNode, currentView); 78192 } else if (tNode.type & 4 78193 /* TNodeType.Container */ 78194 ) { 78195 return createTemplateRef(tNode, currentView); 78196 } 78197 78198 return null; 78199} 78200 78201function createResultForNode(lView, tNode, matchingIdx, read) { 78202 if (matchingIdx === -1) { 78203 // if read token and / or strategy is not specified, detect it using appropriate tNode type 78204 return createResultByTNodeType(tNode, lView); 78205 } else if (matchingIdx === -2) { 78206 // read a special token from a node injector 78207 return createSpecialToken(lView, tNode, read); 78208 } else { 78209 // read a token 78210 return getNodeInjectable(lView, lView[TVIEW], matchingIdx, tNode); 78211 } 78212} 78213 78214function createSpecialToken(lView, tNode, read) { 78215 if (read === ElementRef) { 78216 return createElementRef(tNode, lView); 78217 } else if (read === TemplateRef) { 78218 return createTemplateRef(tNode, lView); 78219 } else if (read === ViewContainerRef) { 78220 ngDevMode && assertTNodeType(tNode, 3 78221 /* TNodeType.AnyRNode */ 78222 | 12 78223 /* TNodeType.AnyContainer */ 78224 ); 78225 return createContainerRef(tNode, lView); 78226 } else { 78227 ngDevMode && throwError(`Special token to read should be one of ElementRef, TemplateRef or ViewContainerRef but got ${stringify(read)}.`); 78228 } 78229} 78230/** 78231 * A helper function that creates query results for a given view. This function is meant to do the 78232 * processing once and only once for a given view instance (a set of results for a given view 78233 * doesn't change). 78234 */ 78235 78236 78237function materializeViewResults(tView, lView, tQuery, queryIndex) { 78238 const lQuery = lView[QUERIES].queries[queryIndex]; 78239 78240 if (lQuery.matches === null) { 78241 const tViewData = tView.data; 78242 const tQueryMatches = tQuery.matches; 78243 const result = []; 78244 78245 for (let i = 0; i < tQueryMatches.length; i += 2) { 78246 const matchedNodeIdx = tQueryMatches[i]; 78247 78248 if (matchedNodeIdx < 0) { 78249 // we at the <ng-template> marker which might have results in views created based on this 78250 // <ng-template> - those results will be in separate views though, so here we just leave 78251 // null as a placeholder 78252 result.push(null); 78253 } else { 78254 ngDevMode && assertIndexInRange(tViewData, matchedNodeIdx); 78255 const tNode = tViewData[matchedNodeIdx]; 78256 result.push(createResultForNode(lView, tNode, tQueryMatches[i + 1], tQuery.metadata.read)); 78257 } 78258 } 78259 78260 lQuery.matches = result; 78261 } 78262 78263 return lQuery.matches; 78264} 78265/** 78266 * A helper function that collects (already materialized) query results from a tree of views, 78267 * starting with a provided LView. 78268 */ 78269 78270 78271function collectQueryResults(tView, lView, queryIndex, result) { 78272 const tQuery = tView.queries.getByIndex(queryIndex); 78273 const tQueryMatches = tQuery.matches; 78274 78275 if (tQueryMatches !== null) { 78276 const lViewResults = materializeViewResults(tView, lView, tQuery, queryIndex); 78277 78278 for (let i = 0; i < tQueryMatches.length; i += 2) { 78279 const tNodeIdx = tQueryMatches[i]; 78280 78281 if (tNodeIdx > 0) { 78282 result.push(lViewResults[i / 2]); 78283 } else { 78284 const childQueryIndex = tQueryMatches[i + 1]; 78285 const declarationLContainer = lView[-tNodeIdx]; 78286 ngDevMode && assertLContainer(declarationLContainer); // collect matches for views inserted in this container 78287 78288 for (let i = CONTAINER_HEADER_OFFSET; i < declarationLContainer.length; i++) { 78289 const embeddedLView = declarationLContainer[i]; 78290 78291 if (embeddedLView[DECLARATION_LCONTAINER] === embeddedLView[PARENT]) { 78292 collectQueryResults(embeddedLView[TVIEW], embeddedLView, childQueryIndex, result); 78293 } 78294 } // collect matches for views created from this declaration container and inserted into 78295 // different containers 78296 78297 78298 if (declarationLContainer[MOVED_VIEWS] !== null) { 78299 const embeddedLViews = declarationLContainer[MOVED_VIEWS]; 78300 78301 for (let i = 0; i < embeddedLViews.length; i++) { 78302 const embeddedLView = embeddedLViews[i]; 78303 collectQueryResults(embeddedLView[TVIEW], embeddedLView, childQueryIndex, result); 78304 } 78305 } 78306 } 78307 } 78308 } 78309 78310 return result; 78311} 78312/** 78313 * Refreshes a query by combining matches from all active views and removing matches from deleted 78314 * views. 78315 * 78316 * @returns `true` if a query got dirty during change detection or if this is a static query 78317 * resolving in creation mode, `false` otherwise. 78318 * 78319 * @codeGenApi 78320 */ 78321 78322 78323function ɵɵqueryRefresh(queryList) { 78324 const lView = getLView(); 78325 const tView = getTView(); 78326 const queryIndex = getCurrentQueryIndex(); 78327 setCurrentQueryIndex(queryIndex + 1); 78328 const tQuery = getTQuery(tView, queryIndex); 78329 78330 if (queryList.dirty && isCreationMode(lView) === ((tQuery.metadata.flags & 2 78331 /* QueryFlags.isStatic */ 78332 ) === 2 78333 /* QueryFlags.isStatic */ 78334 )) { 78335 if (tQuery.matches === null) { 78336 queryList.reset([]); 78337 } else { 78338 const result = tQuery.crossesNgTemplate ? collectQueryResults(tView, lView, queryIndex, []) : materializeViewResults(tView, lView, tQuery, queryIndex); 78339 queryList.reset(result, unwrapElementRef); 78340 queryList.notifyOnChanges(); 78341 } 78342 78343 return true; 78344 } 78345 78346 return false; 78347} 78348/** 78349 * Creates new QueryList, stores the reference in LView and returns QueryList. 78350 * 78351 * @param predicate The type for which the query will search 78352 * @param flags Flags associated with the query 78353 * @param read What to save in the query 78354 * 78355 * @codeGenApi 78356 */ 78357 78358 78359function ɵɵviewQuery(predicate, flags, read) { 78360 ngDevMode && assertNumber(flags, 'Expecting flags'); 78361 const tView = getTView(); 78362 78363 if (tView.firstCreatePass) { 78364 createTQuery(tView, new TQueryMetadata_(predicate, flags, read), -1); 78365 78366 if ((flags & 2 78367 /* QueryFlags.isStatic */ 78368 ) === 2 78369 /* QueryFlags.isStatic */ 78370 ) { 78371 tView.staticViewQueries = true; 78372 } 78373 } 78374 78375 createLQuery(tView, getLView(), flags); 78376} 78377/** 78378 * Registers a QueryList, associated with a content query, for later refresh (part of a view 78379 * refresh). 78380 * 78381 * @param directiveIndex Current directive index 78382 * @param predicate The type for which the query will search 78383 * @param flags Flags associated with the query 78384 * @param read What to save in the query 78385 * @returns QueryList<T> 78386 * 78387 * @codeGenApi 78388 */ 78389 78390 78391function ɵɵcontentQuery(directiveIndex, predicate, flags, read) { 78392 ngDevMode && assertNumber(flags, 'Expecting flags'); 78393 const tView = getTView(); 78394 78395 if (tView.firstCreatePass) { 78396 const tNode = getCurrentTNode(); 78397 createTQuery(tView, new TQueryMetadata_(predicate, flags, read), tNode.index); 78398 saveContentQueryAndDirectiveIndex(tView, directiveIndex); 78399 78400 if ((flags & 2 78401 /* QueryFlags.isStatic */ 78402 ) === 2 78403 /* QueryFlags.isStatic */ 78404 ) { 78405 tView.staticContentQueries = true; 78406 } 78407 } 78408 78409 createLQuery(tView, getLView(), flags); 78410} 78411/** 78412 * Loads a QueryList corresponding to the current view or content query. 78413 * 78414 * @codeGenApi 78415 */ 78416 78417 78418function ɵɵloadQuery() { 78419 return loadQueryInternal(getLView(), getCurrentQueryIndex()); 78420} 78421 78422function loadQueryInternal(lView, queryIndex) { 78423 ngDevMode && assertDefined(lView[QUERIES], 'LQueries should be defined when trying to load a query'); 78424 ngDevMode && assertIndexInRange(lView[QUERIES].queries, queryIndex); 78425 return lView[QUERIES].queries[queryIndex].queryList; 78426} 78427 78428function createLQuery(tView, lView, flags) { 78429 const queryList = new QueryList((flags & 4 78430 /* QueryFlags.emitDistinctChangesOnly */ 78431 ) === 4 78432 /* QueryFlags.emitDistinctChangesOnly */ 78433 ); 78434 storeCleanupWithContext(tView, lView, queryList, queryList.destroy); 78435 if (lView[QUERIES] === null) lView[QUERIES] = new LQueries_(); 78436 lView[QUERIES].queries.push(new LQuery_(queryList)); 78437} 78438 78439function createTQuery(tView, metadata, nodeIndex) { 78440 if (tView.queries === null) tView.queries = new TQueries_(); 78441 tView.queries.track(new TQuery_(metadata, nodeIndex)); 78442} 78443 78444function saveContentQueryAndDirectiveIndex(tView, directiveIndex) { 78445 const tViewContentQueries = tView.contentQueries || (tView.contentQueries = []); 78446 const lastSavedDirectiveIndex = tViewContentQueries.length ? tViewContentQueries[tViewContentQueries.length - 1] :
78446-1; 78447 78448 if (directiveIndex !== lastSavedDirectiveIndex) { 78449 tViewContentQueries.push(tView.queries.length - 1, directiveIndex); 78450 } 78451} 78452 78453function getTQuery(tView, index) { 78454 ngDevMode && assertDefined(tView.queries, 'TQueries must be defined to retrieve a TQuery'); 78455 return tView.queries.getByIndex(index); 78456} 78457/** 78458 * @license 78459 * Copyright Google LLC All Rights Reserved. 78460 * 78461 * Use of this source code is governed by an MIT-style license that can be 78462 * found in the LICENSE file at https://angular.io/license 78463 */ 78464 78465/** 78466 * Retrieves `TemplateRef` instance from `Injector` when a local reference is placed on the 78467 * `<ng-template>` element. 78468 * 78469 * @codeGenApi 78470 */ 78471 78472 78473function ɵɵtemplateRefExtractor(tNode, lView) { 78474 return createTemplateRef(tNode, lView); 78475} 78476/** 78477 * @license 78478 * Copyright Google LLC All Rights Reserved. 78479 * 78480 * Use of this source code is governed by an MIT-style license that can be 78481 * found in the LICENSE file at https://angular.io/license 78482 */ 78483 78484/** 78485 * @license 78486 * Copyright Google LLC All Rights Reserved. 78487 * 78488 * Use of this source code is governed by an MIT-style license that can be 78489 * found in the LICENSE file at https://angular.io/license 78490 */ 78491 78492/** 78493 * A mapping of the @angular/core API surface used in generated expressions to the actual symbols. 78494 * 78495 * This should be kept up to date with the public exports of @angular/core. 78496 */ 78497 78498 78499const angularCoreEnv = (() => ({ 78500 'ɵɵattribute': ɵɵattribute, 78501 'ɵɵattributeInterpolate1': ɵɵattributeInterpolate1, 78502 'ɵɵattributeInterpolate2': ɵɵattributeInterpolate2, 78503 'ɵɵattributeInterpolate3': ɵɵattributeInterpolate3, 78504 'ɵɵattributeInterpolate4': ɵɵattributeInterpolate4, 78505 'ɵɵattributeInterpolate5': ɵɵattributeInterpolate5, 78506 'ɵɵattributeInterpolate6': ɵɵattributeInterpolate6, 78507 'ɵɵattributeInterpolate7': ɵɵattributeInterpolate7, 78508 'ɵɵattributeInterpolate8': ɵɵattributeInterpolate8, 78509 'ɵɵattributeInterpolateV': ɵɵattributeInterpolateV, 78510 'ɵɵdefineComponent': ɵɵdefineComponent, 78511 'ɵɵdefineDirective': ɵɵdefineDirective, 78512 'ɵɵdefineInjectable': ɵɵdefineInjectable, 78513 'ɵɵdefineInjector': ɵɵdefineInjector, 78514 'ɵɵdefineNgModule': ɵɵdefineNgModule, 78515 'ɵɵdefinePipe': ɵɵdefinePipe, 78516 'ɵɵdirectiveInject': ɵɵdirectiveInject, 78517 'ɵɵgetInheritedFactory': ɵɵgetInheritedFactory, 78518 'ɵɵinject': ɵɵinject, 78519 'ɵɵinjectAttribute': ɵɵinjectAttribute, 78520 'ɵɵinvalidFactory': ɵɵinvalidFactory, 78521 'ɵɵinvalidFactoryDep': ɵɵinvalidFactoryDep, 78522 'ɵɵtemplateRefExtractor': ɵɵtemplateRefExtractor, 78523 'ɵɵresetView': ɵɵresetView, 78524 'ɵɵNgOnChangesFeature': ɵɵNgOnChangesFeature, 78525 'ɵɵProvidersFeature': ɵɵProvidersFeature, 78526 'ɵɵCopyDefinitionFeature': ɵɵCopyDefinitionFeature, 78527 'ɵɵInheritDefinitionFeature': ɵɵInheritDefinitionFeature, 78528 'ɵɵStandaloneFeature': ɵɵStandaloneFeature, 78529 'ɵɵnextContext': ɵɵnextContext, 78530 'ɵɵnamespaceHTML': ɵɵnamespaceHTML, 78531 'ɵɵnamespaceMathML': ɵɵnamespaceMathML, 78532 'ɵɵnamespaceSVG': ɵɵnamespaceSVG, 78533 'ɵɵenableBindings': ɵɵenableBindings, 78534 'ɵɵdisableBindings': ɵɵdisableBindings, 78535 'ɵɵelementStart': ɵɵelementStart, 78536 'ɵɵelementEnd': ɵɵelementEnd, 78537 'ɵɵelement': ɵɵelement, 78538 'ɵɵelementContainerStart': ɵɵelementContainerStart, 78539 'ɵɵelementContainerEnd': ɵɵelementContainerEnd, 78540 'ɵɵelementContainer': ɵɵelementContainer, 78541 'ɵɵpureFunction0': ɵɵpureFunction0, 78542 'ɵɵpureFunction1': ɵɵpureFunction1, 78543 'ɵɵpureFunction2': ɵɵpureFunction2, 78544 'ɵɵpureFunction3': ɵɵpureFunction3, 78545 'ɵɵpureFunction4': ɵɵpureFunction4, 78546 'ɵɵpureFunction5': ɵɵpureFunction5, 78547 'ɵɵpureFunction6': ɵɵpureFunction6, 78548 'ɵɵpureFunction7': ɵɵpureFunction7, 78549 'ɵɵpureFunction8': ɵɵpureFunction8, 78550 'ɵɵpureFunctionV': ɵɵpureFunctionV, 78551 'ɵɵgetCurrentView': ɵɵgetCurrentView, 78552 'ɵɵrestoreView': ɵɵrestoreView, 78553 'ɵɵlistener': ɵɵlistener, 78554 'ɵɵprojection': ɵɵprojection, 78555 'ɵɵsyntheticHostProperty': ɵɵsyntheticHostProperty, 78556 'ɵɵsyntheticHostListener': ɵɵsyntheticHostListener, 78557 'ɵɵpipeBind1': ɵɵpipeBind1, 78558 'ɵɵpipeBind2': ɵɵpipeBind2, 78559 'ɵɵpipeBind3': ɵɵpipeBind3, 78560 'ɵɵpipeBind4': ɵɵpipeBind4, 78561 'ɵɵpipeBindV': ɵɵpipeBindV, 78562 'ɵɵprojectionDef': ɵɵprojectionDef, 78563 'ɵɵhostProperty': ɵɵhostProperty, 78564 'ɵɵproperty': ɵɵproperty, 78565 'ɵɵpropertyInterpolate': ɵɵpropertyInterpolate, 78566 'ɵɵpropertyInterpolate1': ɵɵpropertyInterpolate1, 78567 'ɵɵpropertyInterpolate2': ɵɵpropertyInterpolate2, 78568 'ɵɵpropertyInterpolate3': ɵɵpropertyInterpolate3, 78569 'ɵɵpropertyInterpolate4': ɵɵpropertyInterpolate4, 78570 'ɵɵpropertyInterpolate5': ɵɵpropertyInterpolate5, 78571 'ɵɵpropertyInterpolate6': ɵɵpropertyInterpolate6, 78572 'ɵɵpropertyInterpolate7': ɵɵpropertyInterpolate7, 78573 'ɵɵpropertyInterpolate8': ɵɵpropertyInterpolate8, 78574 'ɵɵpropertyInterpolateV': ɵɵpropertyInterpolateV, 78575 'ɵɵpipe': ɵɵpipe, 78576 'ɵɵqueryRefresh': ɵɵqueryRefresh, 78577 'ɵɵviewQuery': ɵɵviewQuery, 78578 'ɵɵloadQuery': ɵɵloadQuery, 78579 'ɵɵcontentQuery': ɵɵcontentQuery, 78580 'ɵɵreference': ɵɵreference, 78581 'ɵɵclassMap': ɵɵclassMap, 78582 'ɵɵclassMapInterpolate1': ɵɵclassMapInterpolate1, 78583 'ɵɵclassMapInterpolate2': ɵɵclassMapInterpolate2, 78584 'ɵɵclassMapInterpolate3': ɵɵclassMapInterpolate3, 78585 'ɵɵclassMapInterpolate4': ɵɵclassMapInterpolate4, 78586 'ɵɵclassMapInterpolate5': ɵɵclassMapInterpolate5, 78587 'ɵɵclassMapInterpolate6': ɵɵclassMapInterpolate6, 78588 'ɵɵclassMapInterpolate7': ɵɵclassMapInterpolate7, 78589 'ɵɵclassMapInterpolate8': ɵɵclassMapInterpolate8, 78590 'ɵɵclassMapInterpolateV': ɵɵclassMapInterpolateV, 78591 'ɵɵstyleMap': ɵɵstyleMap, 78592 'ɵɵstyleMapInterpolate1': ɵɵstyleMapInterpolate1, 78593 'ɵɵstyleMapInterpolate2': ɵɵstyleMapInterpolate2, 78594 'ɵɵstyleMapInterpolate3': ɵɵstyleMapInterpolate3, 78595 'ɵɵstyleMapInterpolate4': ɵɵstyleMapInterpolate4, 78596 'ɵɵstyleMapInterpolate5': ɵɵstyleMapInterpolate5, 78597 'ɵɵstyleMapInterpolate6': ɵɵstyleMapInterpolate6, 78598 'ɵɵstyleMapInterpolate7': ɵɵstyleMapInterpolate7, 78599 'ɵɵstyleMapInterpolate8': ɵɵstyleMapInterpolate8, 78600 'ɵɵstyleMapInterpolateV': ɵɵstyleMapInterpolateV, 78601 'ɵɵstyleProp': ɵɵstyleProp, 78602 'ɵɵstylePropInterpolate1': ɵɵstylePropInterpolate1, 78603 'ɵɵstylePropInterpolate2': ɵɵstylePropInterpolate2, 78604 'ɵɵstylePropInterpolate3': ɵɵstylePropInterpolate3, 78605 'ɵɵstylePropInterpolate4': ɵɵstylePropInterpolate4, 78606 'ɵɵstylePropInterpolate5': ɵɵstylePropInterpolate5, 78607 'ɵɵstylePropInterpolate6': ɵɵstylePropInterpolate6, 78608 'ɵɵstylePropInterpolate7': ɵɵstylePropInterpolate7, 78609 'ɵɵstylePropInterpolate8': ɵɵstylePropInterpolate8, 78610 'ɵɵstylePropInterpolateV': ɵɵstylePropInterpolateV, 78611 'ɵɵclassProp': ɵɵclassProp, 78612 'ɵɵadvance': ɵɵadvance, 78613 'ɵɵtemplate': ɵɵtemplate, 78614 'ɵɵtext': ɵɵtext, 78615 'ɵɵtextInterpolate': ɵɵtextInterpolate, 78616 'ɵɵtextInterpolate1': ɵɵtextInterpolate1, 78617 'ɵɵtextInterpolate2': ɵɵtextInterpolate2, 78618 'ɵɵtextInterpolate3': ɵɵtextInterpolate3, 78619 'ɵɵtextInterpolate4': ɵɵtextInterpolate4, 78620 'ɵɵtextInterpolate5': ɵɵtextInterpolate5, 78621 'ɵɵtextInterpolate6': ɵɵtextInterpolate6, 78622 'ɵɵtextInterpolate7': ɵɵtextInterpolate7, 78623 'ɵɵtextInterpolate8': ɵɵtextInterpolate8, 78624 'ɵɵtextInterpolateV': ɵɵtextInterpolateV, 78625 'ɵɵi18n': ɵɵi18n, 78626 'ɵɵi18nAttributes': ɵɵi18nAttributes, 78627 'ɵɵi18nExp': ɵɵi18nExp, 78628 'ɵɵi18nStart': ɵɵi18nStart, 78629 'ɵɵi18nEnd': ɵɵi18nEnd, 78630 'ɵɵi18nApply': ɵɵi18nApply, 78631 'ɵɵi18nPostprocess': ɵɵi18nPostprocess, 78632 'ɵɵresolveWindow': ɵɵresolveWindow, 78633 'ɵɵresolveDocument': ɵɵresolveDocument, 78634 'ɵɵresolveBody': ɵɵresolveBody, 78635 'ɵɵsetComponentScope': ɵɵsetComponentScope, 78636 'ɵɵsetNgModuleScope': ɵɵsetNgModuleScope, 78637 'ɵɵregisterNgModuleType': registerNgModuleType, 78638 'ɵɵsanitizeHtml': ɵɵsanitizeHtml, 78639 'ɵɵsanitizeStyle': ɵɵsanitizeStyle, 78640 'ɵɵsanitizeResourceUrl': ɵɵsanitizeResourceUrl, 78641 'ɵɵsanitizeScript': ɵɵsanitizeScript, 78642 'ɵɵsanitizeUrl': ɵɵsanitizeUrl, 78643 'ɵɵsanitizeUrlOrResourceUrl': ɵɵsanitizeUrlOrResourceUrl,
vendor: 42,996 bytes, lines 78644-79843
78644 'ɵɵtrustConstantHtml': ɵɵtrustConstantHtml, 78645 'ɵɵtrustConstantResourceUrl': ɵɵtrustConstantResourceUrl, 78646 'forwardRef': forwardRef, 78647 'resolveForwardRef': resolveForwardRef 78648}))(); 78649 78650let jitOptions = null; 78651 78652function setJitOptions(options) { 78653 if (jitOptions !== null) { 78654 if (options.defaultEncapsulation !== jitOptions.defaultEncapsulation) { 78655 ngDevMode && console.error('Provided value for `defaultEncapsulation` can not be changed once it has been set.'); 78656 return; 78657 } 78658 78659 if (options.preserveWhitespaces !== jitOptions.preserveWhitespaces) { 78660 ngDevMode && console.error('Provided value for `preserveWhitespaces` can not be changed once it has been set.'); 78661 return; 78662 } 78663 } 78664 78665 jitOptions = options; 78666} 78667 78668function getJitOptions() { 78669 return jitOptions; 78670} 78671 78672function resetJitOptions() { 78673 jitOptions = null; 78674} 78675/** 78676 * @license 78677 * Copyright Google LLC All Rights Reserved. 78678 * 78679 * Use of this source code is governed by an MIT-style license that can be 78680 * found in the LICENSE file at https://angular.io/license 78681 */ 78682 78683 78684function patchModuleCompilation() {// Does nothing, but exists as a target for patching. 78685} 78686/** 78687 * @license 78688 * Copyright Google LLC All Rights Reserved. 78689 * 78690 * Use of this source code is governed by an MIT-style license that can be 78691 * found in the LICENSE file at https://angular.io/license 78692 */ 78693 78694 78695function isModuleWithProviders(value) { 78696 return value.ngModule !== undefined; 78697} 78698 78699function isNgModule(value) { 78700 return !!getNgModuleDef(value); 78701} 78702/** 78703 * @license 78704 * Copyright Google LLC All Rights Reserved. 78705 * 78706 * Use of this source code is governed by an MIT-style license that can be 78707 * found in the LICENSE file at https://angular.io/license 78708 */ 78709 78710 78711const moduleQueue = []; 78712/** 78713 * Enqueues moduleDef to be checked later to see if scope can be set on its 78714 * component declarations. 78715 */ 78716 78717function enqueueModuleForDelayedScoping(moduleType, ngModule) { 78718 moduleQueue.push({ 78719 moduleType, 78720 ngModule 78721 }); 78722} 78723 78724let flushingModuleQueue = false; 78725/** 78726 * Loops over queued module definitions, if a given module definition has all of its 78727 * declarations resolved, it dequeues that module definition and sets the scope on 78728 * its declarations. 78729 */ 78730 78731function flushModuleScopingQueueAsMuchAsPossible() { 78732 if (!flushingModuleQueue) { 78733 flushingModuleQueue = true; 78734 78735 try { 78736 for (let i = moduleQueue.length - 1; i >= 0; i--) { 78737 const { 78738 moduleType, 78739 ngModule 78740 } = moduleQueue[i]; 78741 78742 if (ngModule.declarations && ngModule.declarations.every(isResolvedDeclaration)) { 78743 // dequeue 78744 moduleQueue.splice(i, 1); 78745 setScopeOnDeclaredComponents(moduleType, ngModule); 78746 } 78747 } 78748 } finally { 78749 flushingModuleQueue = false; 78750 } 78751 } 78752} 78753/** 78754 * Returns truthy if a declaration has resolved. If the declaration happens to be 78755 * an array of declarations, it will recurse to check each declaration in that array 78756 * (which may also be arrays). 78757 */ 78758 78759 78760function isResolvedDeclaration(declaration) { 78761 if (Array.isArray(declaration)) { 78762 return declaration.every(isResolvedDeclaration); 78763 } 78764 78765 return !!resolveForwardRef(declaration); 78766} 78767/** 78768 * Compiles a module in JIT mode. 78769 * 78770 * This function automatically gets called when a class has a `@NgModule` decorator. 78771 */ 78772 78773 78774function compileNgModule(moduleType, ngModule = {}) { 78775 patchModuleCompilation(); 78776 compileNgModuleDefs(moduleType, ngModule); 78777 78778 if (ngModule.id !== undefined) { 78779 registerNgModuleType(moduleType, ngModule.id); 78780 } // Because we don't know if all declarations have resolved yet at the moment the 78781 // NgModule decorator is executing, we're enqueueing the setting of module scope 78782 // on its declarations to be run at a later time when all declarations for the module, 78783 // including forward refs, have resolved. 78784 78785 78786 enqueueModuleForDelayedScoping(moduleType, ngModule); 78787} 78788/** 78789 * Compiles and adds the `ɵmod`, `ɵfac` and `ɵinj` properties to the module class. 78790 * 78791 * It's possible to compile a module via this API which will allow duplicate declarations in its 78792 * root. 78793 */ 78794 78795 78796function compileNgModuleDefs(moduleType, ngModule, allowDuplicateDeclarationsInRoot = false) { 78797 ngDevMode && assertDefined(moduleType, 'Required value moduleType'); 78798 ngDevMode && assertDefined(ngModule, 'Required value ngModule'); 78799 const declarations = flatten(ngModule.declarations || EMPTY_ARRAY); 78800 let ngModuleDef = null; 78801 Object.defineProperty(moduleType, NG_MOD_DEF, { 78802 configurable: true, 78803 get: () => { 78804 if (ngModuleDef === null) { 78805 if (ngDevMode && ngModule.imports && ngModule.imports.indexOf(moduleType) > -1) { 78806 // We need to assert this immediately, because allowing it to continue will cause it to 78807 // go into an infinite loop before we've reached the point where we throw all the errors. 78808 throw new Error(`'${stringifyForError(moduleType)}' module can't import itself`); 78809 } 78810 78811 const compiler = getCompilerFacade({ 78812 usage: 0 78813 /* JitCompilerUsage.Decorator */ 78814 , 78815 kind: 'NgModule', 78816 type: moduleType 78817 }); 78818 ngModuleDef = compiler.compileNgModule(angularCoreEnv, `ng:///${moduleType.name}/ɵmod.js`, { 78819 type: moduleType, 78820 bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY).map(resolveForwardRef), 78821 declarations: declarations.map(resolveForwardRef), 78822 imports: flatten(ngModule.imports || EMPTY_ARRAY).map(resolveForwardRef).map(expandModuleWithProviders), 78823 exports: flatten(ngModule.exports || EMPTY_ARRAY).map(resolveForwardRef).map(expandModuleWithProviders), 78824 schemas: ngModule.schemas ? flatten(ngModule.schemas) : null, 78825 id: ngModule.id || null 78826 }); // Set `schemas` on ngModuleDef to an empty array in JIT mode to indicate that runtime 78827 // should verify that there are no unknown elements in a template. In AOT mode, that check 78828 // happens at compile time and `schemas` information is not present on Component and Module 78829 // defs after compilation (so the check doesn't happen the second time at runtime). 78830 78831 if (!ngModuleDef.schemas) { 78832 ngModuleDef.schemas = []; 78833 } 78834 } 78835 78836 return ngModuleDef; 78837 } 78838 }); 78839 let ngFactoryDef = null; 78840 Object.defineProperty(moduleType, NG_FACTORY_DEF, { 78841 get: () => { 78842 if (ngFactoryDef === null) { 78843 const compiler = getCompilerFacade({ 78844 usage: 0 78845 /* JitCompilerUsage.Decorator */ 78846 , 78847 kind: 'NgModule', 78848 type: moduleType 78849 }); 78850 ngFactoryDef = compiler.compileFactory(angularCoreEnv, `ng:///${moduleType.name}/ɵfac.js`, { 78851 name: moduleType.name, 78852 type: moduleType, 78853 deps: reflectDependencies(moduleType), 78854 target: compiler.FactoryTarget.NgModule, 78855 typeArgumentCount: 0 78856 }); 78857 } 78858 78859 return ngFactoryDef; 78860 }, 78861 // Make the property configurable in dev mode to allow overriding in tests 78862 configurable: !!ngDevMode 78863 }); 78864 let ngInjectorDef = null; 78865 Object.defineProperty(moduleType, NG_INJ_DEF, { 78866 get: () => { 78867 if (ngInjectorDef === null) { 78868 ngDevMode && verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRoot); 78869 const meta = { 78870 name: moduleType.name, 78871 type: moduleType, 78872 providers: ngModule.providers || EMPTY_ARRAY, 78873 imports: [(ngModule.imports || EMPTY_ARRAY).map(resolveForwardRef), (ngModule.exports || EMPTY_ARRAY).map(resolveForwardRef)] 78874 }; 78875 const compiler = getCompilerFacade({ 78876 usage: 0 78877 /* JitCompilerUsage.Decorator */ 78878 , 78879 kind: 'NgModule', 78880 type: moduleType 78881 }); 78882 ngInjectorDef = compiler.compileInjector(angularCoreEnv, `ng:///${moduleType.name}/ɵinj.js`, meta); 78883 } 78884 78885 return ngInjectorDef; 78886 }, 78887 // Make the property configurable in dev mode to allow overriding in tests 78888 configurable: !!ngDevMode 78889 }); 78890} 78891 78892function generateStandaloneInDeclarationsError(type, location) { 78893 const prefix = `Unexpected "${stringifyForError(type)}" found in the "declarations" array of the`; 78894 const suffix = `"${stringifyForError(type)}" is marked as standalone and can't be declared ` + 'in any NgModule - did you intend to import it instead (by adding it to the "imports" array)?'; 78895 return `${prefix} ${location}, ${suffix}`; 78896} 78897 78898function verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRoot, importingModule) { 78899 if (verifiedNgModule.get(moduleType)) return; // skip verifications of standalone components, directives, and pipes 78900 78901 if (isStandalone(moduleType)) return; 78902 verifiedNgModule.set(moduleType, true); 78903 moduleType = resolveForwardRef(moduleType); 78904 let ngModuleDef; 78905 78906 if (importingModule) { 78907 ngModuleDef = getNgModuleDef(moduleType); 78908 78909 if (!ngModuleDef) { 78910 throw new Error(`Unexpected value '${moduleType.name}' imported by the module '${importingModule.name}'. Please add an @NgModule annotation.`); 78911 } 78912 } else { 78913 ngModuleDef = getNgModuleDef(moduleType, true); 78914 } 78915 78916 const errors = []; 78917 const declarations = maybeUnwrapFn(ngModuleDef.declarations); 78918 const imports = maybeUnwrapFn(ngModuleDef.imports); 78919 flatten(imports).map(unwrapModuleWithProvidersImports).forEach(modOrStandaloneCmpt => { 78920 verifySemanticsOfNgModuleImport(modOrStandaloneCmpt, moduleType); 78921 verifySemanticsOfNgModuleDef(modOrStandaloneCmpt, false, moduleType); 78922 }); 78923 const exports = maybeUnwrapFn(ngModuleDef.exports); 78924 declarations.forEach(verifyDeclarationsHaveDefinitions); 78925 declarations.forEach(verifyDirectivesHaveSelector); 78926 declarations.forEach(declarationType => verifyNotStandalone(declarationType, moduleType)); 78927 const combinedDeclarations = [...declarations.map(resolveForwardRef), ...flatten(imports.map(computeCombinedExports)).map(resolveForwardRef)]; 78928 exports.forEach(verifyExportsAreDeclaredOrReExported); 78929 declarations.forEach(decl => verifyDeclarationIsUnique(decl, allowDuplicateDeclarationsInRoot)); 78930 declarations.forEach(verifyComponentEntryComponentsIsPartOfNgModule); 78931 const ngModule = getAnnotation(moduleType, 'NgModule'); 78932 78933 if (ngModule) { 78934 ngModule.imports && flatten(ngModule.imports).map(unwrapModuleWithProvidersImports).forEach(mod => { 78935 verifySemanticsOfNgModuleImport(mod, moduleType); 78936 verifySemanticsOfNgModuleDef(mod, false, moduleType); 78937 }); 78938 ngModule.bootstrap && deepForEach(ngModule.bootstrap, verifyCorrectBootstrapType); 78939 ngModule.bootstrap && deepForEach(ngModule.bootstrap, verifyComponentIsPartOfNgModule); 78940 ngModule.entryComponents && deepForEach(ngModule.entryComponents, verifyComponentIsPartOfNgModule); 78941 } // Throw Error if any errors were detected. 78942 78943 78944 if (errors.length) { 78945 throw new Error(errors.join('\n')); 78946 } //////////////////////////////////////////////////////////////////////////////////////////////// 78947 78948 78949 function verifyDeclarationsHaveDefinitions(type) { 78950 type = resolveForwardRef(type); 78951 const def = getComponentDef(type) || getDirectiveDef(type) || getPipeDef$1(type); 78952 78953 if (!def) { 78954 errors.push(`Unexpected value '${stringifyForError(type)}' declared by the module '${stringifyForError(moduleType)}'. Please add a @Pipe/@Directive/@Component annotation.`); 78955 } 78956 } 78957 78958 function verifyDirectivesHaveSelector(type) { 78959 type = resolveForwardRef(type); 78960 const def = getDirectiveDef(type); 78961 78962 if (!getComponentDef(type) && def && def.selectors.length == 0) { 78963 errors.push(`Directive ${stringifyForError(type)} has no selector, please add it!`); 78964 } 78965 } 78966 78967 function verifyNotStandalone(type, moduleType) { 78968 type = resolveForwardRef(type); 78969 const def = getComponentDef(type) || getDirectiveDef(type) || getPipeDef$1(type); 78970 78971 if (def?.standalone) { 78972 const location = `"${stringifyForError(moduleType)}" NgModule`; 78973 errors.push(generateStandaloneInDeclarationsError(type, location)); 78974 } 78975 } 78976 78977 function verifyExportsAreDeclaredOrReExported(type) { 78978 type = resolveForwardRef(type); 78979 const kind = getComponentDef(type) && 'component' || getDirectiveDef(type) && 'directive' || getPipeDef$1(type) && 'pipe'; 78980 78981 if (kind) { 78982 // only checked if we are declared as Component, Directive, or Pipe 78983 // Modules don't need to be declared or imported. 78984 if (combinedDeclarations.lastIndexOf(type) === -1) { 78985 // We are exporting something which we don't explicitly declare or import. 78986 errors.push(`Can't export ${kind} ${stringifyForError(type)} from ${stringifyForError(moduleType)} as it was neither declared nor imported!`); 78987 } 78988 } 78989 } 78990 78991 function verifyDeclarationIsUnique(type, suppressErrors) { 78992 type = resolveForwardRef(type); 78993 const existingModule = ownerNgModule.get(type); 78994 78995 if (existingModule && existingModule !== moduleType) { 78996 if (!suppressErrors) { 78997 const modules = [existingModule, moduleType].map(stringifyForError).sort(); 78998 errors.push(`Type ${stringifyForError(type)} is part of the declarations of 2 modules: ${modules[0]} and ${modules[1]}! ` + `Please consider moving ${stringifyForError(type)} to a higher module that imports ${modules[0]} and ${modules[1]}. ` + `You can also create a new NgModule that exports and includes ${stringifyForError(type)} then import that NgModule in ${modules[0]} and ${modules[1]}.`); 78999 } 79000 } else { 79001 // Mark type as having owner. 79002 ownerNgModule.set(type, moduleType); 79003 } 79004 } 79005 79006 function verifyComponentIsPartOfNgModule(type) { 79007 type = resolveForwardRef(type); 79008 const existingModule = ownerNgModule.get(type); 79009 79010 if (!existingModule && !isStandalone(type)) { 79011 errors.push(`Component ${stringifyForError(type)} is not part of any NgModule or the module has not been imported into your module.`); 79012 } 79013 } 79014 79015 function verifyCorrectBootstrapType(type) { 79016 type = resolveForwardRef(type); 79017 79018 if (!getComponentDef(type)) { 79019 errors.push(`${stringifyForError(type)} cannot be used as an entry component.`); 79020 } 79021 79022 if (isStandalone(type)) { 79023 // Note: this error should be the same as the 79024 // `NGMODULE_BOOTSTRAP_IS_STANDALONE` one in AOT compiler. 79025 errors.push(`The \`${stringifyForError(type)}\` class is a standalone component, which can ` + `not be used in the \`@NgModule.bootstrap\` array. Use the \`bootstrapApplication\` ` + `function for bootstrap instead.`); 79026 } 79027 } 79028 79029 function verifyComponentEntryComponentsIsPartOfNgModule(type) { 79030 type = resolveForwardRef(type); 79031 79032 if (getComponentDef(type)) { 79033 // We know we are component 79034 const component = getAnnotation(type, 'Component'); 79035 79036 if (component && component.entryComponents) { 79037 deepForEach(component.entryComponents, verifyComponentIsPartOfNgModule); 79038 } 79039 } 79040 } 79041 79042 function verifySemanticsOfNgModuleImport(type, importingModule) { 79043 type = resolveForwardRef(type); 79044 const directiveDef = getComponentDef(type) || getDirectiveDef(type); 79045 79046 if (directiveDef !== null && !directiveDef.standalone) { 79047 throw new Error(`Unexpected directive '${type.name}' imported by the module '${importingModule.name}'. Please add an @NgModule annotation.`); 79048 } 79049 79050 const pipeDef = getPipeDef$1(type); 79051 79052 if (pipeDef !== null && !pipeDef.standalone) { 79053 throw new Error(`Unexpected pipe '${type.name}' imported by the module '${importingModule.name}'. Please add an @NgModule annotation.`); 79054 } 79055 } 79056} 79057 79058function unwrapModuleWithProvidersImports(typeOrWithProviders) { 79059 typeOrWithProviders = resolveForwardRef(typeOrWithProviders); 79060 return typeOrWithProviders.ngModule || typeOrWithProviders; 79061} 79062 79063function getAnnotation(type, name) { 79064 let annotation = null; 79065 collect(type.__annotations__); 79066 collect(type.decorators); 79067 return annotation; 79068 79069 function collect(annotations) { 79070 if (annotations) { 79071 annotations.forEach(readAnnotation); 79072 } 79073 } 79074 79075 function readAnnotation(decorator) { 79076 if (!annotation) { 79077 const proto = Object.getPrototypeOf(decorator); 79078 79079 if (proto.ngMetadataName == name) { 79080 annotation = decorator; 79081 } else if (decorator.type) { 79082 const proto = Object.getPrototypeOf(decorator.type); 79083 79084 if (proto.ngMetadataName == name) { 79085 annotation = decorator.args[0]; 79086 } 79087 } 79088 } 79089 } 79090} 79091/** 79092 * Keep track of compiled components. This is needed because in tests we often want to compile the 79093 * same component with more than one NgModule. This would cause an error unless we reset which 79094 * NgModule the component belongs to. We keep the list of compiled components here so that the 79095 * TestBed can reset it later. 79096 */ 79097 79098 79099let ownerNgModule = new WeakMap(); 79100let verifiedNgModule = new WeakMap(); 79101 79102function resetCompiledComponents() { 79103 ownerNgModule = new WeakMap(); 79104 verifiedNgModule = new WeakMap(); 79105 moduleQueue.length = 0; 79106} 79107/** 79108 * Computes the combined declarations of explicit declarations, as well as declarations inherited by 79109 * traversing the exports of imported modules. 79110 * @param type 79111 */ 79112 79113 79114function computeCombinedExports(type) { 79115 type = resolveForwardRef(type); 79116 const ngModuleDef = getNgModuleDef(type); // a standalone component, directive or pipe 79117 79118 if (ngModuleDef === null) { 79119 return [type]; 79120 } 79121 79122 return [...flatten(maybeUnwrapFn(ngModuleDef.exports).map(type => { 79123 const ngModuleDef = getNgModuleDef(type); 79124 79125 if (ngModuleDef) { 79126 verifySemanticsOfNgModuleDef(type, false); 79127 return computeCombinedExports(type); 79128 } else { 79129 return type; 79130 } 79131 }))]; 79132} 79133/** 79134 * Some declared components may be compiled asynchronously, and thus may not have their 79135 * ɵcmp set yet. If this is the case, then a reference to the module is written into 79136 * the `ngSelectorScope` property of the declared type. 79137 */ 79138 79139 79140function setScopeOnDeclaredComponents(moduleType, ngModule) { 79141 const declarations = flatten(ngModule.declarations || EMPTY_ARRAY); 79142 const transitiveScopes = transitiveScopesFor(moduleType); 79143 declarations.forEach(declaration => { 79144 declaration = resolveForwardRef(declaration); 79145 79146 if (declaration.hasOwnProperty(NG_COMP_DEF)) { 79147 // A `ɵcmp` field exists - go ahead and patch the component directly. 79148 const component = declaration; 79149 const componentDef = getComponentDef(component); 79150 patchComponentDefWithScope(componentDef, transitiveScopes); 79151 } else if (!declaration.hasOwnProperty(NG_DIR_DEF) && !declaration.hasOwnProperty(NG_PIPE_DEF)) { 79152 // Set `ngSelectorScope` for future reference when the component compilation finishes. 79153 declaration.ngSelectorScope = moduleType; 79154 } 79155 }); 79156} 79157/** 79158 * Patch the definition of a component with directives and pipes from the compilation scope of 79159 * a given module. 79160 */ 79161 79162 79163function patchComponentDefWithScope(componentDef, transitiveScopes) { 79164 componentDef.directiveDefs = () => Array.from(transitiveScopes.compilation.directives).map(dir => dir.hasOwnProperty(NG_COMP_DEF) ? getComponentDef(dir) : getDirectiveDef(dir)).filter(def => !!def); 79165 79166 componentDef.pipeDefs = () => Array.from(transitiveScopes.compilation.pipes).map(pipe => getPipeDef$1(pipe)); 79167 79168 componentDef.schemas = transitiveScopes.schemas; // Since we avoid Components/Directives/Pipes recompiling in case there are no overrides, we 79169 // may face a problem where previously compiled defs available to a given Component/Directive 79170 // are cached in TView and may become stale (in case any of these defs gets recompiled). In 79171 // order to avoid this problem, we force fresh TView to be created. 79172 79173 componentDef.tView = null; 79174} 79175/** 79176 * Compute the pair of transitive scopes (compilation scope and exported scope) for a given type 79177 * (either a NgModule or a standalone component / directive / pipe). 79178 */ 79179 79180 79181function transitiveScopesFor(type) { 79182 if (isNgModule(type)) { 79183 return transitiveScopesForNgModule(type); 79184 } else if (isStandalone(type)) { 79185 const directiveDef = getComponentDef(type) || getDirectiveDef(type); 79186 79187 if (directiveDef !== null) { 79188 return { 79189 schemas: null, 79190 compilation: { 79191 directives: new Set(), 79192 pipes: new Set() 79193 }, 79194 exported: { 79195 directives: new Set([type]), 79196 pipes: new Set() 79197 } 79198 }; 79199 } 79200 79201 const pipeDef = getPipeDef$1(type); 79202 79203 if (pipeDef !== null) { 79204 return { 79205 schemas: null, 79206 compilation: { 79207 directives: new Set(), 79208 pipes: new Set() 79209 }, 79210 exported: { 79211 directives: new Set(), 79212 pipes: new Set([type]) 79213 } 79214 }; 79215 } 79216 } // TODO: change the error message to be more user-facing and take standalone into account 79217 79218 79219 throw new Error(`${type.name} does not have a module def (ɵmod property)`); 79220} 79221/** 79222 * Compute the pair of transitive scopes (compilation scope and exported scope) for a given module. 79223 * 79224 * This operation is memoized and the result is cached on the module's definition. This function can 79225 * be called on modules with components that have not fully compiled yet, but the result should not 79226 * be used until they have. 79227 * 79228 * @param moduleType module that transitive scope should be calculated for. 79229 */ 79230 79231 79232function transitiveScopesForNgModule(moduleType) { 79233 const def = getNgModuleDef(moduleType, true); 79234 79235 if (def.transitiveCompileScopes !== null) { 79236 return def.transitiveCompileScopes; 79237 } 79238 79239 const scopes = { 79240 schemas: def.schemas || null, 79241 compilation: { 79242 directives: new Set(), 79243 pipes: new Set() 79244 }, 79245 exported: { 79246 directives: new Set(), 79247 pipes: new Set() 79248 } 79249 }; 79250 maybeUnwrapFn(def.imports).forEach(imported => { 79251 // When this module imports another, the imported module's exported directives and pipes are 79252 // added to the compilation scope of this module. 79253 const importedScope = transitiveScopesFor(imported); 79254 importedScope.exported.directives.forEach(entry => scopes.compilation.directives.add(entry)); 79255 importedScope.exported.pipes.forEach(entry => scopes.compilation.pipes.add(entry)); 79256 }); 79257 maybeUnwrapFn(def.declarations).forEach(declared => { 79258 const declaredWithDefs = declared; 79259 79260 if (getPipeDef$1(declaredWithDefs)) { 79261 scopes.compilation.pipes.add(declared); 79262 } else { 79263 // Either declared has a ɵcmp or ɵdir, or it's a component which hasn't 79264 // had its template compiled yet. In either case, it gets added to the compilation's 79265 // directives. 79266 scopes.compilation.directives.add(declared); 79267 } 79268 }); 79269 maybeUnwrapFn(def.exports).forEach(exported => { 79270 const exportedType = exported; // Either the type is a module, a pipe, or a component/directive (which may not have a 79271 // ɵcmp as it might be compiled asynchronously). 79272 79273 if (isNgModule(exportedType)) { 79274 // When this module exports another, the exported module's exported directives and pipes are 79275 // added to both the compilation and exported scopes of this module. 79276 const exportedScope = transitiveScopesFor(exportedType); 79277 exportedScope.exported.directives.forEach(entry => { 79278 scopes.compilation.directives.add(entry); 79279 scopes.exported.directives.add(entry); 79280 }); 79281 exportedScope.exported.pipes.forEach(entry => { 79282 scopes.compilation.pipes.add(entry); 79283 scopes.exported.pipes.add(entry); 79284 }); 79285 } else if (getPipeDef$1(exportedType)) { 79286 scopes.exported.pipes.add(exportedType); 79287 } else { 79288 scopes.exported.directives.add(exportedType); 79289 } 79290 }); 79291 def.transitiveCompileScopes = scopes; 79292 return scopes; 79293} 79294 79295function expandModuleWithProviders(value) { 79296 if (isModuleWithProviders(value)) { 79297 return value.ngModule; 79298 } 79299 79300 return value; 79301} 79302/** 79303 * @license 79304 * Copyright Google LLC All Rights Reserved. 79305 * 79306 * Use of this source code is governed by an MIT-style license that can be 79307 * found in the LICENSE file at https://angular.io/license 79308 */ 79309 79310/** 79311 * Keep track of the compilation depth to avoid reentrancy issues during JIT compilation. This 79312 * matters in the following scenario: 79313 * 79314 * Consider a component 'A' that extends component 'B', both declared in module 'M'. During 79315 * the compilation of 'A' the definition of 'B' is requested to capture the inheritance chain, 79316 * potentially triggering compilation of 'B'. If this nested compilation were to trigger 79317 * `flushModuleScopingQueueAsMuchAsPossible` it may happen that module 'M' is still pending in the 79318 * queue, resulting in 'A' and 'B' to be patched with the NgModule scope. As the compilation of 79319 * 'A' is still in progress, this would introduce a circular dependency on its compilation. To avoid 79320 * this issue, the module scope queue is only flushed for compilations at the depth 0, to ensure 79321 * all compilations have finished. 79322 */ 79323 79324 79325let compilationDepth = 0; 79326/** 79327 * Compile an Angular component according to its decorator metadata, and patch the resulting 79328 * component def (ɵcmp) onto the component type. 79329 * 79330 * Compilation may be asynchronous (due to the need to resolve URLs for the component template or 79331 * other resources, for example). In the event that compilation is not immediate, `compileComponent` 79332 * will enqueue resource resolution into a global queue and will fail to return the `ɵcmp` 79333 * until the global queue has been resolved with a call to `resolveComponentResources`. 79334 */ 79335 79336function compileComponent(type, metadata) { 79337 // Initialize ngDevMode. This must be the first statement in compileComponent. 79338 // See the `initNgDevMode` docstring for more information. 79339 (typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode(); 79340 let ngComponentDef = null; // Metadata may have resources which need to be resolved. 79341 79342 maybeQueueResolutionOfComponentResources(type, metadata); // Note that we're using the same function as `Directive`, because that's only subset of metadata 79343 // that we need to create the ngFactoryDef. We're avoiding using the component metadata 79344 // because we'd have to resolve the asynchronous templates. 79345 79346 addDirectiveFactoryDef(type, metadata); 79347 Object.defineProperty(type, NG_COMP_DEF, { 79348 get: () => { 79349 if (ngComponentDef === null) { 79350 const compiler = getCompilerFacade({ 79351 usage: 0 79352 /* JitCompilerUsage.Decorator */ 79353 , 79354 kind: 'component', 79355 type: type 79356 }); 79357 79358 if (componentNeedsResolution(metadata)) { 79359 const error = [`Component '${type.name}' is not resolved:`]; 79360 79361 if (metadata.templateUrl) { 79362 error.push(` - templateUrl: ${metadata.templateUrl}`); 79363 } 79364 79365 if (metadata.styleUrls && metadata.styleUrls.length) { 79366 error.push(` - styleUrls: ${JSON.stringify(metadata.styleUrls)}`); 79367 } 79368 79369 error.push(`Did you run and wait for 'resolveComponentResources()'?`); 79370 throw new Error(error.join('\n')); 79371 } // This const was called `jitOptions` previously but had to be renamed to `options` because 79372 // of a bug with Terser that caused optimized JIT builds to throw a `ReferenceError`. 79373 // This bug was investigated in https://github.com/angular/angular-cli/issues/17264. 79374 // We should not rename it back until https://github.com/terser/terser/issues/615 is fixed. 79375 79376 79377 const options = getJitOptions(); 79378 let preserveWhitespaces = metadata.preserveWhitespaces; 79379 79380 if (preserveWhitespaces === undefined) { 79381 if (options !== null && options.preserveWhitespaces !== undefined) { 79382 preserveWhitespaces = options.preserveWhitespaces; 79383 } else { 79384 preserveWhitespaces = false; 79385 } 79386 } 79387 79388 let encapsulation = metadata.encapsulation; 79389 79390 if (encapsulation === undefined) { 79391 if (options !== null && options.defaultEncapsulation !== undefined) { 79392 encapsulation = options.defaultEncapsulation; 79393 } else { 79394 encapsulation = ViewEncapsulation$1.Emulated; 79395 } 79396 } 79397 79398 const templateUrl = metadata.templateUrl || `ng:///${type.name}/template.html`; 79399 const meta = { ...directiveMetadata(type, metadata), 79400 typeSourceSpan: compiler.createParseSourceSpan('Component', type.name, templateUrl), 79401 template: metadata.template || '', 79402 preserveWhitespaces, 79403 styles: metadata.styles || EMPTY_ARRAY, 79404 animations: metadata.animations, 79405 // JIT components are always compiled against an empty set of `declarations`. Instead, the 79406 // `directiveDefs` and `pipeDefs` are updated at a later point: 79407 // * for NgModule-based components, they're set when the NgModule which declares the 79408 // component resolves in the module scoping queue 79409 // * for standalone components, they're set just below, after `compileComponent`. 79410 declarations: [], 79411 changeDetection: metadata.changeDetection, 79412 encapsulation, 79413 interpolation: metadata.interpolation, 79414 viewProviders: metadata.viewProviders || null, 79415 isStandalone: !!metadata.standalone 79416 }; 79417 compilationDepth++; 79418 79419 try { 79420 if (meta.usesInheritance) { 79421 addDirectiveDefToUndecoratedParents(type); 79422 } 79423 79424 ngComponentDef = compiler.compileComponent(angularCoreEnv, templateUrl, meta); 79425 79426 if (metadata.standalone) { 79427 // Patch the component definition for standalone components with `directiveDefs` and 79428 // `pipeDefs` functions which lazily compute the directives/pipes available in the 79429 // standalone component. Also set `dependencies` to the lazily resolved list of imports. 79430 const imports = flatten(metadata.imports || EMPTY_ARRAY); 79431 const { 79432 directiveDefs, 79433 pipeDefs 79434 } = getStandaloneDefFunctions(type, imports); 79435 ngComponentDef.directiveDefs = directiveDefs; 79436 ngComponentDef.pipeDefs = pipeDefs; 79437 79438 ngComponentDef.dependencies = () => imports.map(resolveForwardRef); 79439 } 79440 } finally { 79441 // Ensure that the compilation depth is decremented even when the compilation failed. 79442 compilationDepth--; 79443 } 79444 79445 if (compilationDepth === 0) { 79446 // When NgModule decorator executed, we enqueued the module definition such that 79447 // it would only dequeue and add itself as module scope to all of its declarations, 79448 // but only if if all of its declarations had resolved. This call runs the check 79449 // to see if any modules that are in the queue can be dequeued and add scope to 79450 // their declarations. 79451 flushModuleScopingQueueAsMuchAsPossible(); 79452 } // If component compilation is async, then the @NgModule annotation which declares the 79453 // component may execute and set an ngSelectorScope property on the component type. This 79454 // allows the component to patch itself with directiveDefs from the module after it 79455 // finishes compiling. 79456 79457 79458 if (hasSelectorScope(type)) { 79459 const scopes = transitiveScopesFor(type.ngSelectorScope); 79460 patchComponentDefWithScope(ngComponentDef, scopes); 79461 } 79462 79463 if (metadata.schemas) { 79464 if (metadata.standalone) { 79465 ngComponentDef.schemas = metadata.schemas; 79466 } else { 79467 throw new Error(`The 'schemas' was specified for the ${stringifyForError(type)} but is only valid on a component that is standalone.`); 79468 } 79469 } else if (metadata.standalone) { 79470 ngComponentDef.schemas = []; 79471 } 79472 } 79473 79474 return ngComponentDef; 79475 }, 79476 // Make the property configurable in dev mode to allow overriding in tests 79477 configurable: !!ngDevMode 79478 }); 79479} 79480 79481function getDependencyTypeForError(type) { 79482 if (getComponentDef(type)) return 'component'; 79483 if (getDirectiveDef(type)) return 'directive'; 79484 if (getPipeDef$1(type)) return 'pipe'; 79485 return 'type'; 79486} 79487 79488function verifyStandaloneImport(depType, importingType) { 79489 if (isForwardRef(depType)) { 79490 depType = resolveForwardRef(depType); 79491 79492 if (!depType) { 79493 throw new Error(`Expected forwardRef function, imported from "${stringifyForError(importingType)}", to return a standalone entity or NgModule but got "${stringifyForError(depType) || depType}".`); 79494 } 79495 } 79496 79497 if (getNgModuleDef(depType) == null) { 79498 const def = getComponentDef(depType) || getDirectiveDef(depType) || getPipeDef$1(depType); 79499 79500 if (def != null) { 79501 // if a component, directive or pipe is imported make sure that it is standalone 79502 if (!def.standalone) { 79503 throw new Error(`The "${stringifyForError(depType)}" ${getDependencyTypeForError(depType)}, imported from "${stringifyForError(importingType)}", is not standalone. Did you forget to add the standalone: true flag?`); 79504 } 79505 } else { 79506 // it can be either a module with provider or an unknown (not annotated) type 79507 if (isModuleWithProviders(depType)) { 79508 throw new Error(`A module with providers was imported from "${stringifyForError(importingType)}". Modules with providers are not supported in standalone components imports.`); 79509 } else { 79510 throw new Error(`The "${stringifyForError(depType)}" type, imported from "${stringifyForError(importingType)}", must be a standalone component / directive / pipe or an NgModule. Did you forget to add the required @Component / @Directive / @Pipe or @NgModule annotation?`); 79511 } 79512 } 79513 } 79514} 79515/** 79516 * Build memoized `directiveDefs` and `pipeDefs` functions for the component definition of a 79517 * standalone component, which process `imports` and filter out directives and pipes. The use of 79518 * memoized functions here allows for the delayed resolution of any `forwardRef`s present in the 79519 * component's `imports`. 79520 */ 79521 79522 79523function getStandaloneDefFunctions(type, imports) { 79524 let cachedDirectiveDefs = null; 79525 let cachedPipeDefs = null; 79526 79527 const directiveDefs = () => { 79528 if (cachedDirectiveDefs === null) { 79529 // Standalone components are always able to self-reference, so include the component's own 79530 // definition in its `directiveDefs`. 79531 cachedDirectiveDefs = [getComponentDef(type)]; 79532 const seen = new Set(); 79533 79534 for (const rawDep of imports) { 79535 ngDevMode && verifyStandaloneImport(rawDep, type); 79536 const dep = resolveForwardRef(rawDep); 79537 79538 if (seen.has(dep)) { 79539 continue; 79540 } 79541 79542 seen.add(dep); 79543 79544 if (!!getNgModuleDef(dep)) { 79545 const scope = transitiveScopesFor(dep); 79546 79547 for (const dir of scope.exported.directives) { 79548 const def = getComponentDef(dir) || getDirectiveDef(dir); 79549 79550 if (def && !seen.has(dir)) { 79551 seen.add(dir); 79552 cachedDirectiveDefs.push(def); 79553 } 79554 } 79555 } else { 79556 const def = getComponentDef(dep) || getDirectiveDef(dep); 79557 79558 if (def) { 79559 cachedDirectiveDefs.push(def); 79560 } 79561 } 79562 } 79563 } 79564 79565 return cachedDirectiveDefs; 79566 }; 79567 79568 const pipeDefs = () => { 79569 if (cachedPipeDefs === null) { 79570 cachedPipeDefs = []; 79571 const seen = new Set(); 79572 79573 for (const rawDep of imports) { 79574 const dep = resolveForwardRef(rawDep); 79575 79576 if (seen.has(dep)) { 79577 continue; 79578 } 79579 79580 seen.add(dep); 79581 79582 if (!!getNgModuleDef(dep)) { 79583 const scope = transitiveScopesFor(dep); 79584 79585 for (const pipe of scope.exported.pipes) { 79586 const def = getPipeDef$1(pipe); 79587 79588 if (def && !seen.has(pipe)) { 79589 seen.add(pipe); 79590 cachedPipeDefs.push(def); 79591 } 79592 } 79593 } else { 79594 const def = getPipeDef$1(dep); 79595 79596 if (def) { 79597 cachedPipeDefs.push(def); 79598 } 79599 } 79600 } 79601 } 79602 79603 return cachedPipeDefs; 79604 }; 79605 79606 return { 79607 directiveDefs, 79608 pipeDefs 79609 }; 79610} 79611 79612function hasSelectorScope(component) { 79613 return component.ngSelectorScope !== undefined; 79614} 79615/** 79616 * Compile an Angular directive according to its decorator metadata, and patch the resulting 79617 * directive def onto the component type. 79618 * 79619 * In the event that compilation is not immediate, `compileDirective` will return a `Promise` which 79620 * will resolve when compilation completes and the directive becomes usable. 79621 */ 79622 79623 79624function compileDirective(type, directive) { 79625 let ngDirectiveDef = null; 79626 addDirectiveFactoryDef(type, directive || {}); 79627 Object.defineProperty(type, NG_DIR_DEF, { 79628 get: () => { 79629 if (ngDirectiveDef === null) { 79630 // `directive` can be null in the case of abstract directives as a base class 79631 // that use `@Directive()` with no selector. In that case, pass empty object to the 79632 // `directiveMetadata` function instead of null. 79633 const meta = getDirectiveMetadata(type, directive || {}); 79634 const compiler = getCompilerFacade({ 79635 usage: 0 79636 /* JitCompilerUsage.Decorator */ 79637 , 79638 kind: 'directive', 79639 type 79640 }); 79641 ngDirectiveDef = compiler.compileDirective(angularCoreEnv, meta.sourceMapUrl, meta.metadata); 79642 } 79643 79644 return ngDirectiveDef; 79645 }, 79646 // Make the property configurable in dev mode to allow overriding in tests 79647 configurable: !!ngDevMode 79648 }); 79649} 79650 79651function getDirectiveMetadata(type, metadata) { 79652 const name = type && type.name; 79653 const sourceMapUrl = `ng:///${name}/ɵdir.js`; 79654 const compiler = getCompilerFacade({ 79655 usage: 0 79656 /* JitCompilerUsage.Decorator */ 79657 , 79658 kind: 'directive', 79659 type 79660 }); 79661 const facade = directiveMetadata(type, metadata); 79662 facade.typeSourceSpan = compiler.createParseSourceSpan('Directive', name, sourceMapUrl); 79663 79664 if (facade.usesInheritance) { 79665 addDirectiveDefToUndecoratedParents(type); 79666 } 79667 79668 return { 79669 metadata: facade, 79670 sourceMapUrl 79671 }; 79672} 79673 79674function addDirectiveFactoryDef(type, metadata) { 79675 let ngFactoryDef = null; 79676 Object.defineProperty(type, NG_FACTORY_DEF, { 79677 get: () => { 79678 if (ngFactoryDef === null) { 79679 const meta = getDirectiveMetadata(type, metadata); 79680 const compiler = getCompilerFacade({ 79681 usage: 0 79682 /* JitCompilerUsage.Decorator */ 79683 , 79684 kind: 'directive', 79685 type 79686 }); 79687 ngFactoryDef = compiler.compileFactory(angularCoreEnv, `ng:///${type.name}/ɵfac.js`, { 79688 name: meta.metadata.name, 79689 type: meta.metadata.type, 79690 typeArgumentCount: 0, 79691 deps: reflectDependencies(type), 79692 target: compiler.FactoryTarget.Directive 79693 }); 79694 } 79695 79696 return ngFactoryDef; 79697 }, 79698 // Make the property configurable in dev mode to allow overriding in tests 79699 configurable: !!ngDevMode 79700 }); 79701} 79702 79703function extendsDirectlyFromObject(type) { 79704 return Object.getPrototypeOf(type.prototype) === Object.prototype; 79705} 79706/** 79707 * Extract the `R3DirectiveMetadata` for a particular directive (either a `Directive` or a 79708 * `Component`). 79709 */ 79710 79711 79712function directiveMetadata(type, metadata) { 79713 // Reflect inputs and outputs. 79714 const reflect = getReflect(); 79715 const propMetadata = reflect.ownPropMetadata(type); 79716 return { 79717 name: type.name, 79718 type: type, 79719 selector: metadata.selector !== undefined ? metadata.selector : null, 79720 host: metadata.host || EMPTY_OBJ, 79721 propMetadata: propMetadata, 79722 inputs: metadata.inputs || EMPTY_ARRAY, 79723 outputs: metadata.outputs || EMPTY_ARRAY, 79724 queries: extractQueriesMetadata(type, propMetadata, isContentQuery), 79725 lifecycle: { 79726 usesOnChanges: reflect.hasLifecycleHook(type, 'ngOnChanges') 79727 }, 79728 typeSourceSpan: null, 79729 usesInheritance: !extendsDirectlyFromObject(type), 79730 exportAs: extractExportAs(metadata.exportAs), 79731 providers: metadata.providers || null, 79732 viewQueries: extractQueriesMetadata(type, propMetadata, isViewQuery), 79733 isStandalone: !!metadata.standalone 79734 }; 79735} 79736/** 79737 * Adds a directive definition to all parent classes of a type that don't have an Angular decorator. 79738 */ 79739 79740 79741function addDirectiveDefToUndecoratedParents(type) { 79742 const objPrototype = Object.prototype; 79743 let parent = Object.getPrototypeOf(type.prototype).constructor; // Go up the prototype until we hit `Object`. 79744 79745 while (parent && parent !== objPrototype) { 79746 // Since inheritance works if the class was annotated already, we only need to add 79747 // the def if there are no annotations and the def hasn't been created already. 79748 if (!getDirectiveDef(parent) && !getComponentDef(parent) && shouldAddAbstractDirective(parent)) { 79749 compileDirective(parent, null); 79750 } 79751 79752 parent = Object.getPrototypeOf(parent); 79753 } 79754} 79755 79756function convertToR3QueryPredicate(selector) { 79757 return typeof selector === 'string' ? splitByComma(selector) : resolveForwardRef(selector); 79758} 79759 79760function convertToR3QueryMetadata(propertyName, ann) { 79761 return { 79762 propertyName: propertyName, 79763 predicate: convertToR3QueryPredicate(ann.selector), 79764 descendants: ann.descendants, 79765 first: ann.first, 79766 read: ann.read ? ann.read : null, 79767 static: !!ann.static, 79768 emitDistinctChangesOnly: !!ann.emitDistinctChangesOnly 79769 }; 79770} 79771 79772function extractQueriesMetadata(type, propMetadata, isQueryAnn) { 79773 const queriesMeta = []; 79774 79775 for (const field in propMetadata) { 79776 if (propMetadata.hasOwnProperty(field)) { 79777 const annotations = propMetadata[field]; 79778 annotations.forEach(ann => { 79779 if (isQueryAnn(ann)) { 79780 if (!ann.selector) { 79781 throw new Error(`Can't construct a query for the property "${field}" of ` + `"${stringifyForError(type)}" since the query selector wasn't defined.`); 79782 } 79783 79784 if (annotations.some(isInputAnnotation)) { 79785 throw new Error(`Cannot combine @Input decorators with query decorators`); 79786 } 79787 79788 queriesMeta.push(convertToR3QueryMetadata(field, ann)); 79789 } 79790 }); 79791 } 79792 } 79793 79794 return queriesMeta; 79795} 79796 79797function extractExportAs(exportAs) { 79798 return exportAs === undefined ? null : splitByComma(exportAs); 79799} 79800 79801function isContentQuery(value) { 79802 const name = value.ngMetadataName; 79803 return name === 'ContentChild' || name === 'ContentChildren'; 79804} 79805 79806function isViewQuery(value) { 79807 const name = value.ngMetadataName; 79808 return name === 'ViewChild' || name === 'ViewChildren'; 79809} 79810 79811function isInputAnnotation(value) { 79812 return value.ngMetadataName === 'Input'; 79813} 79814 79815function splitByComma(value) { 79816 return value.split(',').map(piece => piece.trim()); 79817} 79818 79819const LIFECYCLE_HOOKS = ['ngOnChanges', 'ngOnInit', 'ngOnDestroy', 'ngDoCheck', 'ngAfterViewInit', 'ngAfterViewChecked', 'ngAfterContentInit', 'ngAfterContentChecked']; 79820 79821function shouldAddAbstractDirective(type) { 79822 const reflect = getReflect(); 79823 79824 if (LIFECYCLE_HOOKS.some(hookName => reflect.hasLifecycleHook(type, hookName))) { 79825 return true; 79826 } 79827 79828 const propMetadata = reflect.propMetadata(type); 79829 79830 for (const field in propMetadata) { 79831 const annotations = propMetadata[field]; 79832 79833 for (let i = 0; i < annotations.length; i++) { 79834 const current = annotations[i]; 79835 const metadataName = current.ngMetadataName; 79836 79837 if (isInputAnnotation(current) || isContentQuery(current) || isViewQuery(current) || metadataName === 'Output' || metadataName === 'HostBinding' || metadataName === 'HostListener') { 79838 return true; 79839 } 79840 } 79841 } 79842 79843 return false;
79844} 79845/** 79846 * @license 79847 * Copyright Google LLC All Rights Reserved. 79848 * 79849 * Use of this source code is governed by an MIT-style license that can be 79850 * found in the LICENSE file at https://angular.io/license 79851 */ 79852 79853 79854function compilePipe(type, meta) { 79855 let ngPipeDef = null; 79856 let ngFactoryDef = null; 79857 Object.defineProperty(type, NG_FACTORY_DEF, { 79858 get: () => { 79859 if (ngFactoryDef === null) { 79860 const metadata = getPipeMetadata(type, meta); 79861 const compiler = getCompilerFacade({ 79862 usage: 0 79863 /* JitCompilerUsage.Decorator */ 79864 , 79865 kind: 'pipe', 79866 type: metadata.type 79867 }); 79868 ngFactoryDef = compiler.compileFactory(angularCoreEnv, `ng:///${metadata.name}/ɵfac.js`, { 79869 name: metadata.name, 79870 type: metadata.type, 79871 typeArgumentCount: 0, 79872 deps: reflectDependencies(type), 79873 target: compiler.FactoryTarget.Pipe 79874 }); 79875 } 79876 79877 return ngFactoryDef; 79878 }, 79879 // Make the property configurable in dev mode to allow overriding in tests 79880 configurable: !!ngDevMode 79881 }); 79882 Object.defineProperty(type, NG_PIPE_DEF, { 79883 get: () => { 79884 if (ngPipeDef === null) { 79885 const metadata = getPipeMetadata(type, meta); 79886 const compiler = getCompilerFacade({ 79887 usage: 0 79888 /* JitCompilerUsage.Decorator */ 79889 , 79890 kind: 'pipe', 79891 type: metadata.type 79892 }); 79893 ngPipeDef = compiler.compilePipe(angularCoreEnv, `ng:///${metadata.name}/ɵpipe.js`, metadata); 79894 } 79895 79896 return ngPipeDef; 79897 }, 79898 // Make the property configurable in dev mode to allow overriding in tests 79899 configurable: !!ngDevMode 79900 }); 79901} 79902 79903function getPipeMetadata(type, meta) { 79904 return { 79905 type: type, 79906 name: type.name, 79907 pipeName: meta.name, 79908 pure: meta.pure !== undefined ? meta.pure : true, 79909 isStandalone: !!meta.standalone 79910 }; 79911} 79912/** 79913 * @license 79914 * Copyright Google LLC All Rights Reserved. 79915 * 79916 * Use of this source code is governed by an MIT-style license that can be 79917 * found in the LICENSE file at https://angular.io/license 79918 */ 79919 79920/** 79921 * Type of the Directive metadata. 79922 * 79923 * @publicApi 79924 */ 79925 79926 79927const Directive = makeDecorator('Directive', (dir = {}) => dir, undefined, undefined, (type, meta) => compileDirective(type, meta)); 79928/** 79929 * Component decorator and metadata. 79930 * 79931 * @Annotation 79932 * @publicApi 79933 */ 79934 79935const Component = makeDecorator('Component', (c = {}) => ({ 79936 changeDetection: ChangeDetectionStrategy.Default, 79937 ...c 79938}), Directive, undefined, (type, meta) => compileComponent(type, meta)); 79939/** 79940 * @Annotation 79941 * @publicApi 79942 */ 79943 79944const Pipe = makeDecorator('Pipe', p => ({ 79945 pure: true, 79946 ...p 79947}), undefined, undefined, (type, meta) => compilePipe(type, meta)); 79948/** 79949 * @Annotation 79950 * @publicApi 79951 */ 79952 79953const Input = makePropDecorator('Input', bindingPropertyName => ({ 79954 bindingPropertyName 79955})); 79956/** 79957 * @Annotation 79958 * @publicApi 79959 */ 79960 79961const Output = makePropDecorator('Output', bindingPropertyName => ({ 79962 bindingPropertyName 79963})); 79964/** 79965 * @Annotation 79966 * @publicApi 79967 */ 79968 79969const HostBinding = makePropDecorator('HostBinding', hostPropertyName => ({ 79970 hostPropertyName 79971})); 79972/** 79973 * Decorator that binds a DOM event to a host listener and supplies configuration metadata. 79974 * Angular invokes the supplied handler method when the host element emits the specified event, 79975 * and updates the bound element with the result. 79976 * 79977 * If the handler method returns false, applies `preventDefault` on the bound element. 79978 * 79979 * @usageNotes 79980 * 79981 * The following example declares a directive 79982 * that attaches a click listener to a button and counts clicks. 79983 * 79984 * ```ts 79985 * @Directive({selector: 'button[counting]'}) 79986 * class CountClicks { 79987 * numberOfClicks = 0; 79988 * 79989 * @HostListener('click', ['$event.target']) 79990 * onClick(btn) { 79991 * console.log('button', btn, 'number of clicks:', this.numberOfClicks++); 79992 * } 79993 * } 79994 * 79995 * @Component({ 79996 * selector: 'app', 79997 * template: '<button counting>Increment</button>', 79998 * }) 79999 * class App {} 80000 * 80001 * ``` 80002 * 80003 * The following example registers another DOM event handler that listens for `Enter` key-press 80004 * events on the global `window`. 80005 * ``` ts 80006 * import { HostListener, Component } from "@angular/core"; 80007 * 80008 * @Component({ 80009 * selector: 'app', 80010 * template: `<h1>Hello, you have pressed enter {{counter}} number of times!</h1> Press enter key 80011 * to increment the counter. 80012 * <button (click)="resetCounter()">Reset Counter</button>` 80013 * }) 80014 * class AppComponent { 80015 * counter = 0; 80016 * @HostListener('window:keydown.enter', ['$event']) 80017 * handleKeyDown(event: KeyboardEvent) { 80018 * this.counter++; 80019 * } 80020 * resetCounter() { 80021 * this.counter = 0; 80022 * } 80023 * } 80024 * ``` 80025 * The list of valid key names for `keydown` and `keyup` events 80026 * can be found here: 80027 * https://www.w3.org/TR/DOM-Level-3-Events-key/#named-key-attribute-values 80028 *
80029 * Note that keys can also be combined, e.g. `@HostListener('keydown.shift.a')`. 80030 * 80031 * The global target names that can be used to prefix an event name are 80032 * `document:`, `window:` and `body:`. 80033 * 80034 * @Annotation 80035 * @publicApi 80036 */ 80037 80038const HostListener = makePropDecorator('HostListener', (eventName, args) => ({ 80039 eventName, 80040 args 80041})); 80042/** 80043 * @license 80044 * Copyright Google LLC All Rights Reserved. 80045 * 80046 * Use of this source code is governed by an MIT-style license that can be 80047 * found in the LICENSE file at https://angular.io/license 80048 */ 80049 80050/** 80051 * @Annotation 80052 * @publicApi 80053 */ 80054 80055const NgModule = makeDecorator('NgModule', ngModule => ngModule, undefined, undefined, 80056/** 80057 * Decorator that marks the following class as an NgModule, and supplies 80058 * configuration metadata for it. 80059 * 80060 * * The `declarations` and `entryComponents` options configure the compiler 80061 * with information about what belongs to the NgModule. 80062 * * The `providers` options configures the NgModule's injector to provide 80063 * dependencies the NgModule members. 80064 * * The `imports` and `exports` options bring in members from other modules, and make 80065 * this module's members available to others. 80066 */ 80067(type, meta) => compileNgModule(type, meta)); 80068/** 80069 * @license 80070 * Copyright Google LLC All Rights Reserved. 80071 * 80072 * Use of this source code is governed by an MIT-style license that can be 80073 * found in the LICENSE file at https://angular.io/license 80074 */ 80075 80076/** 80077 * @license 80078 * Copyright Google LLC All Rights Reserved. 80079 * 80080 * Use of this source code is governed by an MIT-style license that can be 80081 * found in the LICENSE file at https://angular.io/license 80082 */ 80083 80084/** 80085 * @license 80086 * Copyright Google LLC All Rights Reserved. 80087 * 80088 * Use of this source code is governed by an MIT-style license that can be 80089 * found in the LICENSE file at https://angular.io/license 80090 */ 80091 80092function noop(...args) {// Do nothing. 80093} 80094/** 80095 * @license 80096 * Copyright Google LLC All Rights Reserved. 80097 * 80098 * Use of this source code is governed by an MIT-style license that can be 80099 * found in the LICENSE file at https://angular.io/license 80100 */ 80101 80102/** 80103 * The existence of this constant (in this particular file) informs the Angular compiler that the 80104 * current program is actually @angular/core, which needs to be compiled specially. 80105 */ 80106 80107 80108const ITS_JUST_ANGULAR = true; 80109/** 80110 * A [DI token](guide/glossary#di-token "DI token definition") that you can use to provide 80111 * one or more initialization functions. 80112 * 80113 * The provided functions are injected at application startup and executed during 80114 * app initialization. If any of these functions returns a Promise or an Observable, initialization 80115 * does not complete until the Promise is resolved or the Observable is completed. 80116 * 80117 * You can, for example, create a factory function that loads language data 80118 * or an external configuration, and provide that function to the `APP_INITIALIZER` token. 80119 * The function is executed during the application bootstrap process, 80120 * and the needed data is available on startup. 80121 * 80122 * @see `ApplicationInitStatus` 80123 * 80124 * @usageNotes 80125 * 80126 * The following example illustrates how to configure a multi-provider using `APP_INITIALIZER` token 80127 * and a function returning a promise. 80128 * 80129 * ``` 80130 * function initializeApp(): Promise<any> { 80131 * return new Promise((resolve, reject) => { 80132 * // Do some asynchronous stuff 80133 * resolve(); 80134 * }); 80135 * } 80136 * 80137 * @NgModule({ 80138 * imports: [BrowserModule], 80139 * declarations: [AppComponent], 80140 * bootstrap: [AppComponent], 80141 * providers: [{ 80142 * provide: APP_INITIALIZER, 80143 * useFactory: () => initializeApp, 80144 * multi: true 80145 * }] 80146 * }) 80147 * export class AppModule {} 80148 * ``` 80149 * 80150 * It's also possible to configure a multi-provider using `APP_INITIALIZER` token and a function 80151 * returning an observable, see an example below. Note: the `HttpClient` in this example is used for 80152 * demo purposes to illustrate how the factory function can work with other providers available 80153 * through DI. 80154 * 80155 * ``` 80156 * function initializeAppFactory(httpClient: HttpClient): () => Observable<any> { 80157 * return () => httpClient.get("https://someUrl.com/api/user") 80158 * .pipe( 80159 * tap(user => { ... }) 80160 * ); 80161 * } 80162 * 80163 * @NgModule({ 80164 * imports: [BrowserModule, HttpClientModule], 80165 * declarations: [AppComponent], 80166 * bootstrap: [AppComponent], 80167 * providers: [{ 80168 * provide: APP_INITIALIZER, 80169 * useFactory: initializeAppFactory, 80170 * deps: [HttpClient], 80171 * multi: true 80172 * }] 80173 * }) 80174 * export class AppModule {} 80175 * ``` 80176 * 80177 * @publicApi 80178 */ 80179 80180const APP_INITIALIZER = new InjectionToken('Application Initializer'); 80181/** 80182 * A class that reflects the state of running {@link APP_INITIALIZER} functions. 80183 * 80184 * @publicApi 80185 */ 80186 80187class ApplicationInitStatus { 80188 constructor(appInits) { 80189 this.appInits = appInits; 80190 this.resolve = noop; 80191 this.reject = noop; 80192 this.initialized = false;
80193 this.done = false; 80194 this.donePromise = new Promise((res, rej) => { 80195 this.resolve = res; 80196 this.reject = rej; 80197 }); 80198 } 80199 /** @internal */ 80200 80201 80202 runInitializers() { 80203 if (this.initialized) { 80204 return; 80205 } 80206 80207 const asyncInitPromises = []; 80208 80209 const complete = () => { 80210 this.done = true; 80211 this.resolve(); 80212 }; 80213 80214 if (this.appInits) { 80215 for (let i = 0; i < this.appInits.length; i++) { 80216 const initResult = this.appInits[i](); 80217 80218 if (isPromise(initResult)) { 80219 asyncInitPromises.push(initResult); 80220 } else if (isObservable(initResult)) { 80221 const observableAsPromise = new Promise((resolve, reject) => { 80222 initResult.subscribe({ 80223 complete: resolve, 80224 error: reject 80225 }); 80226 }); 80227 asyncInitPromises.push(observableAsPromise); 80228 } 80229 } 80230 } 80231 80232 Promise.all(asyncInitPromises).then(() => { 80233 complete(); 80234 }).catch(e => { 80235 this.reject(e); 80236 }); 80237 80238 if (asyncInitPromises.length === 0) { 80239 complete(); 80240 } 80241 80242 this.initialized = true; 80243 } 80244 80245} 80246 80247ApplicationInitStatus.ɵfac = function ApplicationInitStatus_Factory(t) { 80248 return new (t || ApplicationInitStatus)(ɵɵinject(APP_INITIALIZER, 8)); 80249}; 80250 80251ApplicationInitStatus.ɵprov = /*@__PURE__*/ɵɵdefineInjectable({ 80252 token: ApplicationInitStatus, 80253 factory: ApplicationInitStatus.ɵfac, 80254 providedIn: 'root' 80255}); 80256 80257(function () { 80258 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationInitStatus, [{ 80259 type: Injectable, 80260 args: [{ 80261 providedIn: 'root' 80262 }] 80263 }], function () { 80264 return [{ 80265 type: undefined, 80266 decorators: [{ 80267 type: Inject, 80268 args: [APP_INITIALIZER] 80269 }, { 80270 type: Optional 80271 }] 80272 }]; 80273 }, null); 80274})(); 80275/** 80276 * @license 80277 * Copyright Google LLC All Rights Reserved. 80278 * 80279 * Use of this source code is governed by an MIT-style license that can be 80280 * found in the LICENSE file at https://angular.io/license 80281 */ 80282 80283/** 80284 * A [DI token](guide/glossary#di-token "DI token definition") representing a unique string ID, used 80285 * primarily for prefixing application attributes and CSS styles when 80286 * {@link ViewEncapsulation#Emulated ViewEncapsulation.Emulated} is being used. 80287 * 80288 * BY default, the value is randomly generated and assigned to the application by Angular. 80289 * To provide a custom ID value, use a DI provider <!-- TODO: provider --> to configure 80290 * the root {@link Injector} that uses this token. 80291 * 80292 * @publicApi 80293 */ 80294 80295 80296const APP_ID = new InjectionToken('AppId', { 80297 providedIn: 'root', 80298 factory: _appIdRandomProviderFactory 80299}); 80300 80301function _appIdRandomProviderFactory() { 80302 return `${_randomChar()}${_randomChar()}${_randomChar()}`; 80303} 80304/** 80305 * Providers that generate a random `APP_ID_TOKEN`. 80306 * @publicApi 80307 */ 80308 80309 80310const APP_ID_RANDOM_PROVIDER = { 80311 provide: APP_ID, 80312 useFactory: _appIdRandomProviderFactory, 80313 deps: [] 80314}; 80315 80316function _randomChar() { 80317 return String.fromCharCode(97 + Math.floor(Math.random() * 25)); 80318} 80319/** 80320 * A function that is executed when a platform is initialized. 80321 * @publicApi 80322 */ 80323 80324 80325const PLATFORM_INITIALIZER = new InjectionToken('Platform Initializer'); 80326/** 80327 * A token that indicates an opaque platform ID. 80328 * @publicApi 80329 */ 80330 80331const PLATFORM_ID = new InjectionToken('Platform ID', { 80332 providedIn: 'platform', 80333 factory: () => 'unknown' // set a default platform name, when none set explicitly 80334 80335}); 80336/** 80337 * A [DI token](guide/glossary#di-token "DI token definition") that provides a set of callbacks to 80338 * be called for every component that is bootstrapped. 80339 * 80340 * Each callback must take a `ComponentRef` instance and return nothing. 80341 * 80342 * `(componentRef: ComponentRef) => void` 80343 * 80344 * @publicApi 80345 */ 80346 80347const APP_BOOTSTRAP_LISTENER = new InjectionToken('appBootstrapListener'); 80348/** 80349 * A [DI token](guide/glossary#di-token "DI token definition") that indicates the root directory of 80350 * the application 80351 * @publicApi 80352 */ 80353 80354const PACKAGE_ROOT_URL = new InjectionToken('Application Packages Root URL'); // We keep this token here, rather than the animations package, so that modules that only care 80355// about which animations module is loaded (e.g. the CDK) can retrieve it without having to 80356// include extra dependencies. See #44970 for more context. 80357 80358/** 80359 * A [DI token](guide/glossary#di-token "DI token definition") that indicates which animations 80360 * module has been loaded. 80361 * @publicApi 80362 */ 80363 80364const ANIMATION_MODULE_TYPE = new InjectionToken('AnimationModuleType'); 80365/** 80366 * @license 80367 * Copyright Google LLC All Rights Reserved. 80368 * 80369 * Use of this source code is governed by an MIT-style license that can be 80370 * found in the LICENSE file at https://angular.io/license 80371 */ 80372 80373class Console { 80374 log(message) { 80375 // tslint:disable-next-line:no-console 80376 console.log(message); 80377 } // Note: for reporting errors use `DOM.logError()` as it is platform specific 80378 80379 80380 warn(message) { 80381 // tslint:disable-next-line:no-console 80382 console.warn(message); 80383 } 80384 80385} 80386 80387Console.ɵfac = function Console_Factory(t) { 80388 return new (t || Console)(); 80389}; 80390 80391Console.ɵprov = /*@__PURE__*/ɵɵdefineInjectable({ 80392 token: Console, 80393 factory: Console.ɵfac, 80394 providedIn: 'platform' 80395}); 80396 80397(function () { 80398 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Console, [{ 80399 type: Injectable, 80400 args: [{ 80401 providedIn: 'platform' 80402 }] 80403 }], null, null); 80404})(); 80405/** 80406 * @license 80407 * Copyright Google LLC All Rights Reserved. 80408 * 80409 * Use of this source code is governed by an MIT-style license that can be 80410 * found in the LICENSE file at https://angular.io/license 80411 */ 80412 80413/** 80414 * Work out the locale from the potential global properties. 80415 * 80416 * * Closure Compiler: use `goog.LOCALE`. 80417 * * Ivy enabled: use `$localize.locale` 80418 */ 80419 80420 80421function getGlobalLocale() { 80422 if (typeof ngI18nClosureMode !== 'undefined' && ngI18nClosureMode && typeof goog !== 'undefined' && goog.LOCALE !== 'en') { 80423 // * The default `goog.LOCALE` value is `en`, while Angular used `en-US`. 80424 // * In order to preserve backwards compatibility, we use Angular default value over 80425 // Closure Compiler's one. 80426 return goog.LOCALE; 80427 } else { 80428 // KEEP `typeof $localize !== 'undefined' && $localize.locale` IN SYNC WITH THE LOCALIZE 80429 // COMPILE-TIME INLINER. 80430 // 80431 // * During compile time inlining of translations the expression will be replaced 80432 // with a string literal that is the current locale. Other forms of this expression are not 80433 // guaranteed to be replaced. 80434 // 80435 // * During runtime translation evaluation, the developer is required to set `$localize.locale` 80436 // if required, or just to provide their own `LOCALE_ID` provider. 80437 return typeof $localize !== 'undefined' && $localize.locale || DEFAULT_LOCALE_ID; 80438 } 80439} 80440/**
80441 * Provide this token to set the locale of your application. 80442 * It is used for i18n extraction, by i18n pipes (DatePipe, I18nPluralPipe, CurrencyPipe, 80443 * DecimalPipe and PercentPipe) and by ICU expressions. 80444 * 80445 * See the [i18n guide](guide/i18n-common-locale-id) for more information. 80446 * 80447 * @usageNotes 80448 * ### Example 80449 * 80450 * ```typescript 80451 * import { LOCALE_ID } from '@angular/core'; 80452 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 80453 * import { AppModule } from './app/app.module'; 80454 * 80455 * platformBrowserDynamic().bootstrapModule(AppModule, { 80456 * providers: [{provide: LOCALE_ID, useValue: 'en-US' }] 80457 * }); 80458 * ``` 80459 * 80460 * @publicApi 80461 */ 80462 80463 80464const LOCALE_ID = new InjectionToken('LocaleId', { 80465 providedIn: 'root', 80466 factory: () => inject(LOCALE_ID, InjectFlags.Optional | InjectFlags.SkipSelf) || getGlobalLocale() 80467}); 80468/** 80469 * Provide this token to set the default currency code your application uses for 80470 * CurrencyPipe when there is no currency code passed into it. This is only used by 80471 * CurrencyPipe and has no relation to locale currency. Defaults to USD if not configured. 80472 * 80473 * See the [i18n guide](guide/i18n-common-locale-id) for more information. 80474 * 80475 * <div class="alert is-helpful"> 80476 * 80477 * **Deprecation notice:** 80478 * 80479 * The default currency code is currently always `USD` but this is deprecated from v9. 80480 * 80481 * **In v10 the default currency code will be taken from the current locale.** 80482 * 80483 * If you need the previous behavior then set it by creating a `DEFAULT_CURRENCY_CODE` provider in 80484 * your application `NgModule`: 80485 * 80486 * ```ts 80487 * {provide: DEFAULT_CURRENCY_CODE, useValue: 'USD'} 80488 * ``` 80489 * 80490 * </div> 80491 * 80492 * @usageNotes 80493 * ### Example 80494 * 80495 * ```typescript 80496 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 80497 * import { AppModule } from './app/app.module'; 80498 * 80499 * platformBrowserDynamic().bootstrapModule(AppModule, { 80500 * providers: [{provide: DEFAULT_CURRENCY_CODE, useValue: 'EUR' }] 80501 * }); 80502 * ``` 80503 * 80504 * @publicApi 80505 */ 80506 80507const DEFAULT_CURRENCY_CODE = new InjectionToken('DefaultCurrencyCode', { 80508 providedIn: 'root', 80509 factory: () => USD_CURRENCY_CODE 80510}); 80511/** 80512 * Use this token at bootstrap to provide the content of your translation file (`xtb`, 80513 * `xlf` or `xlf2`) when you want to translate your application in another language. 80514 * 80515 * See the [i18n guide](guide/i18n-common-merge) for more information. 80516 * 80517 * @usageNotes 80518 * ### Example 80519 * 80520 * ```typescript 80521 * import { TRANSLATIONS } from '@angular/core'; 80522 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 80523 * import { AppModule } from './app/app.module'; 80524 * 80525 * // content of your translation file 80526 * const translations = '....'; 80527 * 80528 * platformBrowserDynamic().bootstrapModule(AppModule, { 80529 * providers: [{provide: TRANSLATIONS, useValue: translations }] 80530 * }); 80531 * ``` 80532 * 80533 * @publicApi 80534 */ 80535 80536const TRANSLATIONS = new InjectionToken('Translations'); 80537/** 80538 * Provide this token at bootstrap to set the format of your {@link TRANSLATIONS}: `xtb`, 80539 * `xlf` or `xlf2`. 80540 * 80541 * See the [i18n guide](guide/i18n-common-merge) for more information. 80542 * 80543 * @usageNotes 80544 * ### Example 80545 * 80546 * ```typescript 80547 * import { TRANSLATIONS_FORMAT } from '@angular/core'; 80548 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 80549 * import { AppModule } from './app/app.module'; 80550 * 80551 * platformBrowserDynamic().bootstrapModule(AppModule, { 80552 * providers: [{provide: TRANSLATIONS_FORMAT, useValue: 'xlf' }] 80553 * }); 80554 * ``` 80555 * 80556 * @publicApi 80557 */ 80558 80559const TRANSLATIONS_FORMAT = new InjectionToken('TranslationsFormat'); 80560/** 80561 * Use this enum at bootstrap as an option of `bootstrapModule` to define the strategy 80562 * that the compiler should use in case of missing translations: 80563 * - Error: throw if you have missing translations. 80564 * - Warning (default): show a warning in the console and/or shell. 80565 * - Ignore: do nothing. 80566 * 80567 * See the [i18n guide](guide/i18n-common-merge#report-missing-translations) for more information. 80568 * 80569 * @usageNotes 80570 * ### Example 80571 * ```typescript 80572 * import { MissingTranslationStrategy } from '@angular/core'; 80573 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 80574 * import { AppModule } from './app/app.module';
80575 * 80576 * platformBrowserDynamic().bootstrapModule(AppModule, { 80577 * missingTranslation: MissingTranslationStrategy.Error 80578 * }); 80579 * ``` 80580 * 80581 * @publicApi 80582 */ 80583 80584var MissingTranslationStrategy; 80585 80586(function (MissingTranslationStrategy) { 80587 MissingTranslationStrategy[MissingTranslationStrategy["Error"] = 0] = "Error"; 80588 MissingTranslationStrategy[MissingTranslationStrategy["Warning"] = 1] = "Warning"; 80589 MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore"; 80590})(MissingTranslationStrategy || (MissingTranslationStrategy = {})); 80591/** 80592 * @license 80593 * Copyright Google LLC All Rights Reserved. 80594 * 80595 * Use of this source code is governed by an MIT-style license that can be 80596 * found in the LICENSE file at https://angular.io/license 80597 */ 80598 80599/** 80600 * Combination of NgModuleFactory and ComponentFactories. 80601 * 80602 * @publicApi 80603 * 80604 * @deprecated 80605 * Ivy JIT mode doesn't require accessing this symbol. 80606 * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for 80607 * additional context. 80608 */ 80609 80610 80611class ModuleWithComponentFactories { 80612 constructor(ngModuleFactory, componentFactories) { 80613 this.ngModuleFactory = ngModuleFactory; 80614 this.componentFactories = componentFactories; 80615 } 80616 80617} 80618/** 80619 * Low-level service for running the angular compiler during runtime 80620 * to create {@link ComponentFactory}s, which 80621 * can later be used to create and render a Component instance. 80622 * 80623 * Each `@NgModule` provides an own `Compiler` to its injector, 80624 * that will use the directives/pipes of the ng module for compilation 80625 * of components. 80626 * 80627 * @publicApi 80628 * 80629 * @deprecated 80630 * Ivy JIT mode doesn't require accessing this symbol. 80631 * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for 80632 * additional context. 80633 */ 80634 80635 80636class Compiler { 80637 /** 80638 * Compiles the given NgModule and all of its components. All templates of the components listed 80639 * in `entryComponents` have to be inlined. 80640 */ 80641 compileModuleSync(moduleType) { 80642 return new NgModuleFactory(moduleType); 80643 } 80644 /** 80645 * Compiles the given NgModule and all of its components 80646 */ 80647 80648 80649 compileModuleAsync(moduleType) { 80650 return Promise.resolve(this.compileModuleSync(moduleType)); 80651 } 80652 /** 80653 * Same as {@link #compileModuleSync} but also creates ComponentFactories for all components. 80654 */ 80655 80656 80657 compileModuleAndAllComponentsSync(moduleType) { 80658 const ngModuleFactory = this.compileModuleSync(moduleType); 80659 const moduleDef = getNgModuleDef(moduleType); 80660 const componentFactories = maybeUnwrapFn(moduleDef.declarations).reduce((factories, declaration) => { 80661 const componentDef = getComponentDef(declaration); 80662 componentDef && factories.push(new ComponentFactory(componentDef)); 80663 return factories; 80664 }, []); 80665 return new ModuleWithComponentFactories(ngModuleFactory, componentFactories); 80666 } 80667 /** 80668 * Same as {@link #compileModuleAsync} but also creates ComponentFactories for all components. 80669 */ 80670 80671 80672 compileModuleAndAllComponentsAsync(moduleType) { 80673 return Promise.resolve(this.compileModuleAndAllComponentsSync(moduleType)); 80674 } 80675 /** 80676 * Clears all caches. 80677 */ 80678 80679 80680 clearCache() {} 80681 /** 80682 * Clears the cache for the given component/ngModule. 80683 */ 80684 80685 80686 clearCacheFor(type) {} 80687 /** 80688 * Returns the id for a given NgModule, if one is defined and known to the compiler. 80689 */ 80690 80691 80692 getModuleId(moduleType) { 80693 return undefined; 80694 } 80695 80696} 80697 80698Compiler.ɵfac = function Compiler_Factory(t) { 80699 return new (t || Compiler)(); 80700}; 80701 80702Compiler.ɵprov = /*@__PURE__*/ɵɵdefineInjectable({ 80703 token: Compiler, 80704 factory: Compiler.ɵfac, 80705 providedIn: 'root' 80706}); 80707 80708(function () { 80709 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Compiler, [{ 80710 type: Injectable, 80711 args: [{ 80712 providedIn: 'root' 80713 }] 80714 }], null, null); 80715})(); 80716/** 80717 * Token to provide CompilerOptions in the platform injector. 80718 * 80719 * @publicApi 80720 */ 80721 80722 80723const COMPILER_OPTIONS = new InjectionToken('compilerOptions'); 80724/** 80725 * A factory for creating a Compiler 80726 * 80727 * @publicApi 80728 * 80729 * @deprecated 80730 * Ivy JIT mode doesn't require accessing this symbol. 80731 * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for 80732 * additional context. 80733 */ 80734 80735class CompilerFactory {} 80736/** 80737 * @license 80738 * Copyright Google LLC All Rights Reserved. 80739 * 80740 * Use of this source code is governed by an MIT-style license that can be 80741 * found in the LICENSE file at https://angular.io/license 80742 */ 80743 80744/** 80745 * Marks a component for check (in case of OnPush components) and synchronously 80746 * performs change detection on the application this component belongs to. 80747 * 80748 * @param component Component to {@link ChangeDetectorRef#markForCheck mark for check}. 80749 * 80750 * @publicApi 80751 * @globalApi ng 80752 */ 80753 80754 80755function applyChanges(component) { 80756 ngDevMode && assertDefined(component, 'component'); 80757 markViewDirty(getComponentViewByInstance(component)); 80758 getRootComponents(component).forEach(rootComponent => detectChanges(rootComponent)); 80759} 80760/** 80761 * @license 80762 * Copyright Google LLC All Rights Reserved. 80763 * 80764 * Use of this source code is governed by an MIT-style license that can be 80765 * found in the LICENSE file at https://angular.io/license 80766 */ 80767 80768/** 80769 * This file introduces series of globally accessible debug tools 80770 * to allow for the Angular debugging story to function. 80771 * 80772 * To see this in action run the following command: 80773 * 80774 * bazel run //packages/core/test/bundling/todo:devserver 80775 * 80776 * Then load `localhost:5432` and start using the console tools. 80777 */ 80778 80779/** 80780 * This value reflects the property on the window where the dev 80781 * tools are patched (window.ng). 80782 * */ 80783 80784 80785const GLOBAL_PUBLISH_EXPANDO_KEY = 'ng'; 80786let _published = false;
80787/** 80788 * Publishes a collection of default debug tools onto`window.ng`. 80789 * 80790 * These functions are available globally when Angular is in development 80791 * mode and are automatically stripped away from prod mode is on. 80792 */ 80793 80794function publishDefaultGlobalUtils$1() { 80795 if (!_published) { 80796 _published = true; 80797 /** 80798 * Warning: this function is *INTERNAL* and should not be relied upon in application's code. 80799 * The contract of the function might be changed in any release and/or the function can be 80800 * removed completely. 80801 */ 80802 80803 publishGlobalUtil('ɵsetProfiler', setProfiler); 80804 publishGlobalUtil('getDirectiveMetadata', getDirectiveMetadata$1); 80805 publishGlobalUtil('getComponent', getComponent); 80806 publishGlobalUtil('getContext', getContext); 80807 publishGlobalUtil('getListeners', getListeners); 80808 publishGlobalUtil('getOwningComponent', getOwningComponent); 80809 publishGlobalUtil('getHostElement', getHostElement); 80810 publishGlobalUtil('getInjector', getInjector); 80811 publishGlobalUtil('getRootComponents', getRootComponents); 80812 publishGlobalUtil('getDirectives', getDirectives); 80813 publishGlobalUtil('applyChanges', applyChanges); 80814 } 80815} 80816/** 80817 * Publishes the given function to `window.ng` so that it can be 80818 * used from the browser console when an application is not in production. 80819 */ 80820 80821 80822function publishGlobalUtil(name, fn) { 80823 if (typeof COMPILED === 'undefined' || !COMPILED) { 80824 // Note: we can't export `ng` when using closure enhanced optimization as: 80825 // - closure declares globals itself for minified names, which sometimes clobber our `ng` global 80826 // - we can't declare a closure extern as the namespace `ng` is already used within Google 80827 // for typings for AngularJS (via `goog.provide('ng....')`). 80828 const w = _global; 80829 ngDevMode && assertDefined(fn, 'function not defined'); 80830 80831 if (w) { 80832 let container = w[GLOBAL_PUBLISH_EXPANDO_KEY]; 80833 80834 if (!container) { 80835 container = w[GLOBAL_PUBLISH_EXPANDO_KEY] = {}; 80836 } 80837 80838 container[name] = fn; 80839 } 80840 } 80841} 80842/** 80843 * @license 80844 * Copyright Google LLC All Rights Reserved. 80845 * 80846 * Use of this source code is governed by an MIT-style license that can be 80847 * found in the LICENSE file at https://angular.io/license 80848 */ 80849 80850 80851const promise = (() => Promise.resolve(0))(); 80852 80853function scheduleMicroTask(fn) { 80854 if (typeof Zone === 'undefined') { 80855 // use promise to schedule microTask instead of use Zone 80856 promise.then(() => { 80857 fn && fn.apply(null, null); 80858 }); 80859 } else { 80860 Zone.current.scheduleMicroTask('scheduleMicrotask', fn); 80861 } 80862} 80863/** 80864 * @license 80865 * Copyright Google LLC All Rights Reserved. 80866 * 80867 * Use of this source code is governed by an MIT-style license that can be 80868 * found in the LICENSE file at https://angular.io/license 80869 */ 80870 80871 80872function getNativeRequestAnimationFrame() { 80873 let nativeRequestAnimationFrame = _global['requestAnimationFrame']; 80874 let nativeCancelAnimationFrame = _global['cancelAnimationFrame']; 80875 80876 if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame && nativeCancelAnimationFrame) { 80877 // use unpatched version of requestAnimationFrame(native delegate) if possible 80878 // to avoid another Change detection 80879 const unpatchedRequestAnimationFrame = nativeRequestAnimationFrame[Zone.__symbol__('OriginalDelegate')]; 80880 80881 if (unpatchedRequestAnimationFrame) { 80882 nativeRequestAnimationFrame = unpatchedRequestAnimationFrame; 80883 } 80884 80885 const unpatchedCancelAnimationFrame = nativeCancelAnimationFrame[Zone.__symbol__('OriginalDelegate')]; 80886 80887 if (unpatchedCancelAnimationFrame) { 80888 nativeCancelAnimationFrame = unpatchedCancelAnimationFrame; 80889 } 80890 } 80891 80892 return { 80893 nativeRequestAnimationFrame, 80894 nativeCancelAnimationFrame 80895 }; 80896} 80897/** 80898 * @license 80899 * Copyright Google LLC All Rights Reserved. 80900 * 80901 * Use of this source code is governed by an MIT-style license that can be 80902 * found in the LICENSE file at https://angular.io/license 80903 */ 80904 80905/** 80906 * An injectable service for executing work inside or outside of the Angular zone. 80907 * 80908 * The most common use of this service is to optimize performance when starting a work consisting of 80909 * one or more asynchronous tasks that don't require UI updates or error handling to be handled by 80910 * Angular. Such tasks can be kicked off via {@link #runOutsideAngular} and if needed, these tasks 80911 * can reenter the Angular zone via {@link #run}. 80912 * 80913 * <!-- TODO: add/fix links to: 80914 * - docs explaining zones and the use of zones in Angular and change-detection 80915 * - link to runOutsideAngular/run (throughout this file!) 80916 * --> 80917 * 80918 * @usageNotes 80919 * ### Example 80920 * 80921 * ``` 80922 * import {Component, NgZone} from '@angular/core'; 80923 * import {NgIf} from '@angular/common'; 80924 * 80925 * @Component({ 80926 * selector: 'ng-zone-demo', 80927 * template: ` 80928 * <h2>Demo: NgZone</h2> 80929 * 80930 * <p>Progress: {{progress}}%</p> 80931 * <p *ngIf="progress >= 100">Done processing {{label}} of Angular zone!</p> 80932 * 80933 * <button (click)="processWithinAngularZone()">Process within Angular zone</button> 80934 * <button (click)="processOutsideOfAngularZone()">Process outside of Angular zone</button> 80935 * `, 80936 * }) 80937 * export class NgZoneDemo { 80938 * progress: number = 0; 80939 * label: string; 80940 * 80941 * constructor(private _ngZone: NgZone) {} 80942 * 80943 * // Loop inside the Angular zone 80944 * // so the UI DOES refresh after each setTimeout cycle 80945 * processWithinAngularZone() { 80946 * this.label = 'inside'; 80947 * this.progress = 0; 80948 * this._increaseProgress(() => console.log('Inside Done!')); 80949 * } 80950 * 80951 * // Loop outside of the Angular zone 80952 * // so the UI DOES NOT refresh after each setTimeout cycle 80953 * processOutsideOfAngularZone() { 80954 * this.label = 'outside'; 80955 * this.progress = 0; 80956 * this._ngZone.runOutsideAngular(() => { 80957 * this._increaseProgress(() => { 80958 * // reenter the Angular zone and display done 80959 * this._ngZone.run(() => { console.log('Outside Done!'); }); 80960 * }); 80961 * }); 80962 * } 80963 * 80964 * _increaseProgress(doneCallback: () => void) { 80965 * this.progress += 1; 80966 * console.log(`Current progress: ${this.progress}%`); 80967 * 80968 * if (this.progress < 100) { 80969 * window.setTimeout(() => this._increaseProgress(doneCallback), 10); 80970 * } else { 80971 * doneCallback(); 80972 * } 80973 * } 80974 * } 80975 * ``` 80976 * 80977 * @publicApi 80978 */ 80979 80980 80981class NgZone {
80982 constructor({ 80983 enableLongStackTrace = false, 80984 shouldCoalesceEventChangeDetection = false, 80985 shouldCoalesceRunChangeDetection = false 80986 }) { 80987 this.hasPendingMacrotasks = false; 80988 this.hasPendingMicrotasks = false; 80989 /** 80990 * Whether there are no outstanding microtasks or macrotasks. 80991 */ 80992 80993 this.isStable = true; 80994 /** 80995 * Notifies when code enters Angular Zone. This gets fired first on VM Turn. 80996 */ 80997 80998 this.onUnstable = new EventEmitter(false); 80999 /** 81000 * Notifies when there is no more microtasks enqueued in the current VM Turn. 81001 * This is a hint for Angular to do change detection, which may enqueue more microtasks. 81002 * For this reason this event can fire multiple times per VM Turn. 81003 */ 81004 81005 this.onMicrotaskEmpty = new EventEmitter(false); 81006 /** 81007 * Notifies when the last `onMicrotaskEmpty` has run and there are no more microtasks, which 81008 * implies we are about to relinquish VM turn. 81009 * This event gets called just once. 81010 */ 81011 81012 this.onStable = new EventEmitter(false); 81013 /** 81014 * Notifies that an error has been delivered. 81015 */ 81016 81017 this.onError = new EventEmitter(false); 81018 81019 if (typeof Zone == 'undefined') { 81020 throw new RuntimeError(908 81021 /* RuntimeErrorCode.MISSING_ZONEJS */ 81022 , ngDevMode && `In this configuration Angular requires Zone.js`); 81023 } 81024 81025 Zone.assertZonePatched(); 81026 const self = this; 81027 self._nesting = 0; 81028 self._outer = self._inner = Zone.current; 81029 81030 if (Zone['AsyncStackTaggingZoneSpec']) { 81031 const AsyncStackTaggingZoneSpec = Zone['AsyncStackTaggingZoneSpec']; 81032 self._inner = self._inner.fork(new AsyncStackTaggingZoneSpec('Angular')); 81033 } 81034 81035 if (Zone['TaskTrackingZoneSpec']) { 81036 self._inner = self._inner.fork(new Zone['TaskTrackingZoneSpec']()); 81037 } 81038 81039 if (enableLongStackTrace && Zone['longStackTraceZoneSpec']) { 81040 self._inner = self._inner.fork(Zone['longStackTraceZoneSpec']); 81041 } // if shouldCoalesceRunChangeDetection is true, all tasks including event tasks will be 81042 // coalesced, so shouldCoalesceEventChangeDetection option is not necessary and can be skipped. 81043 81044 81045 self.shouldCoalesceEventChangeDetection = !shouldCoalesceRunChangeDetection && shouldCoalesceEventChangeDetection; 81046 self.shouldCoalesceRunChangeDetection = shouldCoalesceRunChangeDetection; 81047 self.lastRequestAnimationFrameId = -1; 81048 self.nativeRequestAnimationFrame = getNativeRequestAnimationFrame().nativeRequestAnimationFrame; 81049 forkInnerZoneWithAngularBehavior(self); 81050 } 81051 81052 static isInAngularZone() { 81053 // Zone needs to be checked, because this method might be called even when NoopNgZone is used. 81054 return typeof Zone !== 'undefined' && Zone.current.get('isAngularZone') === true; 81055 } 81056 81057 static assertInAngularZone() { 81058 if (!NgZone.isInAngularZone()) { 81059 throw new RuntimeError(909 81060 /* RuntimeErrorCode.UNEXPECTED_ZONE_STATE */ 81061 , ngDevMode && 'Expected to be in Angular Zone, but it is not!'); 81062 } 81063 } 81064 81065 static assertNotInAngularZone() { 81066 if (NgZone.isInAngularZone()) { 81067 throw new RuntimeError(909 81068 /* RuntimeErrorCode.UNEXPECTED_ZONE_STATE */ 81069 , ngDevMode && 'Expected to not be in Angular Zone, but it is!'); 81070 } 81071 } 81072 /** 81073 * Executes the `fn` function synchronously within the Angular zone and returns value returned by 81074 * the function. 81075 * 81076 * Running functions via `run` allows you to reenter Angular zone from a task that was executed 81077 * outside of the Angular zone (typically started via {@link #runOutsideAngular}). 81078 * 81079 * Any future tasks or microtasks scheduled from within this function will continue executing from 81080 * within the Angular zone. 81081 * 81082 * If a synchronous error happens it will be rethrown and not reported via `onError`. 81083 */ 81084 81085 81086 run(fn, applyThis, applyArgs) { 81087 return this._inner.run(fn, applyThis, applyArgs); 81088 } 81089 /** 81090 * Executes the `fn` function synchronously within the Angular zone as a task and returns value 81091 * returned by the function. 81092 * 81093 * Running functions via `run` allows you to reenter Angular zone from a task that was executed 81094 * outside of the Angular zone (typically started via {@link #runOutsideAngular}). 81095 * 81096 * Any future tasks or microtasks scheduled from within this function will continue executing from 81097 * within the Angular zone. 81098 * 81099 * If a synchronous error happens it will be rethrown and not reported via `onError`. 81100 */ 81101 81102 81103 runTask(fn, applyThis, applyArgs, name) { 81104 const zone = this._inner; 81105 const task = zone.scheduleEventTask('NgZoneEvent: ' + name, fn, E
81105MPTY_PAYLOAD, noop, noop); 81106 81107 try { 81108 return zone.runTask(task, applyThis, applyArgs); 81109 } finally { 81110 zone.cancelTask(task); 81111 } 81112 } 81113 /** 81114 * Same as `run`, except that synchronous errors are caught and forwarded via `onError` and not 81115 * rethrown. 81116 */ 81117 81118 81119 runGuarded(fn, applyThis, applyArgs) { 81120 return this._inner.runGuarded(fn, applyThis, applyArgs); 81121 } 81122 /** 81123 * Executes the `fn` function synchronously in Angular's parent zone and returns value returned by 81124 * the function. 81125 * 81126 * Running functions via {@link #runOutsideAngular} allows you to escape Angular's zone and do 81127 * work that 81128 * doesn't trigger Angular change-detection or is subject to Angular's error handling. 81129 * 81130 * Any future tasks or microtasks scheduled from within this function will continue executing from 81131 * outside of the Angular zone. 81132 * 81133 * Use {@link #run} to reenter the Angular zone and do work that updates the application model. 81134 */ 81135 81136 81137 runOutsideAngular(fn) { 81138 return this._outer.run(fn); 81139 } 81140 81141} 81142 81143const EMPTY_PAYLOAD = {}; 81144 81145function checkStable(zone) { 81146 // TODO: @JiaLiPassion, should check zone.isCheckStableRunning to prevent 81147 // re-entry. The case is: 81148 // 81149 // @Component({...}) 81150 // export class AppComponent { 81151 // constructor(private ngZone: NgZone) { 81152 // this.ngZone.onStable.subscribe(() => { 81153 // this.ngZone.run(() => console.log('stable');); 81154 // }); 81155 // } 81156 // 81157 // The onStable subscriber run another function inside ngZone 81158 // which causes `checkStable()` re-entry. 81159 // But this fix causes some issues in g3, so this fix will be 81160 // launched in another PR. 81161 if (zone._nesting == 0 && !zone.hasPendingMicrotasks && !zone.isStable) { 81162 try { 81163 zone._nesting++; 81164 zone.onMicrotaskEmpty.emit(null); 81165 } finally { 81166 zone._nesting--; 81167 81168 if (!zone.hasPendingMicrotasks) { 81169 try { 81170 zone.runOutsideAngular(() => zone.onStable.emit(null)); 81171 } finally { 81172 zone.isStable = true; 81173 } 81174 } 81175 } 81176 } 81177} 81178 81179function delayChangeDetectionForEvents(zone) { 81180 /** 81181 * We also need to check _nesting here 81182 * Consider the following case with shouldCoalesceRunChangeDetection = true 81183 * 81184 * ngZone.run(() => {}); 81185 * ngZone.run(() => {}); 81186 * 81187 * We want the two `ngZone.run()` only trigger one change detection 81188 * when shouldCoalesceRunChangeDetection is true. 81189 * And because in this case, change detection run in async way(requestAnimationFrame), 81190 * so we also need to check the _nesting here to prevent multiple 81191 * change detections. 81192 */ 81193 if (zone.isCheckStableRunning || zone.lastRequestAnimationFrameId !== -1) { 81194 return; 81195 } 81196 81197 zone.lastRequestAnimationFrameId = zone.nativeRequestAnimationFrame.call(_global, () => { 81198 // This is a work around for https://github.com/angular/angular/issues/36839. 81199 // The core issue is that when event coalescing is enabled it is possible for microtasks 81200 // to get flushed too early (As is the case with `Promise.then`) between the 81201 // coalescing eventTasks. 81202 // 81203 // To workaround this we schedule a "fake" eventTask before we process the 81204 // coalescing eventTasks. The benefit of this is that the "fake" container eventTask 81205 // will prevent the microtasks queue from getting drained in between the coalescing 81206 // eventTask execution. 81207 if (!zone.fakeTopEventTask) { 81208 zone.fakeTopEventTask = Zone.root.scheduleEventTask('fakeTopEventTask', () => { 81209 zone.lastRequestAnimationFrameId = -1; 81210 updateMicroTaskStatus(zone); 81211 zone.isCheckStableRunning = true; 81212 checkStable(zone); 81213 zone.isCheckStableRunning = false; 81214 }, undefined, () => {}, () => {}); 81215 } 81216 81217 zone.fakeTopEventTask.invoke(); 81218 }); 81219 updateMicroTaskStatus(zone); 81220} 81221 81222function forkInnerZoneWithAngularBehavior(zone) { 81223 const delayChangeDetectionForEventsDelegate = () => { 81224 delayChangeDetectionForEvents(zone); 81225 }; 81226 81227 zone._inner = zone._inner.fork({ 81228 name: 'angular', 81229 properties: { 81230 'isAngularZone': true 81231 }, 81232 onInvokeTask: (delegate, current, target, task, applyThis, applyArgs) => {
vendor: 4,770 bytes, lines 81233-81384
81233 try { 81234 onEnter(zone); 81235 return delegate.invokeTask(target, task, applyThis, applyArgs); 81236 } finally { 81237 if (zone.shouldCoalesceEventChangeDetection && task.type === 'eventTask' || zone.shouldCoalesceRunChangeDetection) { 81238 delayChangeDetectionForEventsDelegate(); 81239 } 81240 81241 onLeave(zone); 81242 } 81243 }, 81244 onInvoke: (delegate, current, target, callback, applyThis, applyArgs, source) => { 81245 try { 81246 onEnter(zone); 81247 return delegate.invoke(target, callback, applyThis, applyArgs, source); 81248 } finally { 81249 if (zone.shouldCoalesceRunChangeDetection) { 81250 delayChangeDetectionForEventsDelegate(); 81251 } 81252 81253 onLeave(zone); 81254 } 81255 }, 81256 onHasTask: (delegate, current, target, hasTaskState) => { 81257 delegate.hasTask(target, hasTaskState); 81258 81259 if (current === target) { 81260 // We are only interested in hasTask events which originate from our zone 81261 // (A child hasTask event is not interesting to us) 81262 if (hasTaskState.change == 'microTask') { 81263 zone._hasPendingMicrotasks = hasTaskState.microTask; 81264 updateMicroTaskStatus(zone); 81265 checkStable(zone); 81266 } else if (hasTaskState.change == 'macroTask') { 81267 zone.hasPendingMacrotasks = hasTaskState.macroTask; 81268 } 81269 } 81270 }, 81271 onHandleError: (delegate, current, target, error) => { 81272 delegate.handleError(target, error); 81273 zone.runOutsideAngular(() => zone.onError.emit(error)); 81274 return false; 81275 } 81276 }); 81277} 81278 81279function updateMicroTaskStatus(zone) { 81280 if (zone._hasPendingMicrotasks || (zone.shouldCoalesceEventChangeDetection || zone.shouldCoalesceRunChangeDetection) && zone.lastRequestAnimationFrameId !== -1) { 81281 zone.hasPendingMicrotasks = true; 81282 } else { 81283 zone.hasPendingMicrotasks = false; 81284 } 81285} 81286 81287function onEnter(zone) { 81288 zone._nesting++; 81289 81290 if (zone.isStable) { 81291 zone.isStable = false; 81292 zone.onUnstable.emit(null); 81293 } 81294} 81295 81296function onLeave(zone) { 81297 zone._nesting--; 81298 checkStable(zone); 81299} 81300/** 81301 * Provides a noop implementation of `NgZone` which does nothing. This zone requires explicit calls 81302 * to framework to perform rendering. 81303 */ 81304 81305 81306class NoopNgZone { 81307 constructor() { 81308 this.hasPendingMicrotasks = false; 81309 this.hasPendingMacrotasks = false; 81310 this.isStable = true; 81311 this.onUnstable = new EventEmitter(); 81312 this.onMicrotaskEmpty = new EventEmitter(); 81313 this.onStable = new EventEmitter(); 81314 this.onError = new EventEmitter(); 81315 } 81316 81317 run(fn, applyThis, applyArgs) { 81318 return fn.apply(applyThis, applyArgs); 81319 } 81320 81321 runGuarded(fn, applyThis, applyArgs) { 81322 return fn.apply(applyThis, applyArgs); 81323 } 81324 81325 runOutsideAngular(fn) { 81326 return fn(); 81327 } 81328 81329 runTask(fn, applyThis, applyArgs, name) { 81330 return fn.apply(applyThis, applyArgs); 81331 } 81332 81333} 81334/** 81335 * @license 81336 * Copyright Google LLC All Rights Reserved. 81337 * 81338 * Use of this source code is governed by an MIT-style license that can be 81339 * found in the LICENSE file at https://angular.io/license 81340 */ 81341 81342/** 81343 * Internal injection token that can used to access an instance of a Testability class. 81344 * 81345 * This token acts as a bridge between the core bootstrap code and the `Testability` class. This is 81346 * needed to ensure that there are no direct references to the `Testability` class, so it can be 81347 * tree-shaken away (if not referenced). For the environments/setups when the `Testability` class 81348 * should be available, this token is used to add a provider that references the `Testability` 81349 * class. Otherwise, only this token is retained in a bundle, but the `Testability` class is not. 81350 */ 81351 81352 81353const TESTABILITY = new InjectionToken(''); 81354/** 81355 * Internal injection token to retrieve Testability getter class instance. 81356 */ 81357 81358const TESTABILITY_GETTER = new InjectionToken(''); 81359/** 81360 * The Testability service provides testing hooks that can be accessed from 81361 * the browser. 81362 * 81363 * Angular applications bootstrapped using an NgModule (via `@NgModule.bootstrap` field) will also 81364 * instantiate Testability by default (in both development and production modes). 81365 * 81366 * For applications bootstrapped using the `bootstrapApplication` function, Testability is not 81367 * included by default. You can include it into your applications by getting the list of necessary 81368 * providers using the `provideProtractorTestingSupport()` function and adding them into the 81369 * `options.providers` array. Example: 81370 * 81371 * ```typescript 81372 * import {provideProtractorTestingSupport} from '@angular/platform-browser'; 81373 * 81374 * await bootstrapApplication(RootComponent, providers: [provideProtractorTestingSupport()]); 81375 * ``` 81376 * 81377 * @publicApi 81378 */ 81379 81380class Testability { 81381 constructor(_ngZone, registry, testabilityGetter) { 81382 this._ngZone = _ngZone; 81383 this.registry = registry; 81384 this._pendingCount = 0;
81385 this._isZoneStable = true; 81386 /** 81387 * Whether any work was done since the last 'whenStable' callback. This is 81388 * useful to detect if this could have potentially destabilized another 81389 * component while it is stabilizing. 81390 * @internal 81391 */ 81392 81393 this._didWork = false; 81394 this._callbacks = []; 81395 this.taskTrackingZone = null; // If there was no Testability logic registered in the global scope 81396 // before, register the current testability getter as a global one. 81397 81398 if (!_testabilityGetter) { 81399 setTestabilityGetter(testabilityGetter); 81400 testabilityGetter.addToWindow(registry); 81401 } 81402 81403 this._watchAngularEvents(); 81404 81405 _ngZone.run(() => { 81406 this.taskTrackingZone = typeof Zone == 'undefined' ? null : Zone.current.get('TaskTrackingZone'); 81407 }); 81408 } 81409 81410 _watchAngularEvents() { 81411 this._ngZone.onUnstable.subscribe({ 81412 next: () => { 81413 this._didWork = true; 81414 this._isZoneStable = false; 81415 } 81416 }); 81417 81418 this._ngZone.runOutsideAngular(() => { 81419 this._ngZone.onStable.subscribe({ 81420 next: () => { 81421 NgZone.assertNotInAngularZone(); 81422 scheduleMicroTask(() => { 81423 this._isZoneStable = true; 81424 81425 this._runCallbacksIfReady(); 81426 }); 81427 } 81428 }); 81429 }); 81430 } 81431 /** 81432 * Increases the number of pending request 81433 * @deprecated pending requests are now tracked with zones. 81434 */ 81435 81436 81437 increasePendingRequestCount() { 81438 this._pendingCount += 1; 81439 this._didWork = true; 81440 return this._pendingCount; 81441 } 81442 /** 81443 * Decreases the number of pending request 81444 * @deprecated pending requests are now tracked with zones 81445 */ 81446 81447 81448 decreasePendingRequestCount() { 81449 this._pendingCount -= 1; 81450 81451 if (this._pendingCount < 0) { 81452 throw new Error('pending async requests below zero'); 81453 } 81454 81455 this._runCallbacksIfReady(); 81456 81457 return this._pendingCount; 81458 } 81459 /** 81460 * Whether an associated application is stable 81461 */ 81462 81463 81464 isStable() { 81465 return this._isZoneStable && this._pendingCount === 0 && !this._ngZone.hasPendingMacrotasks; 81466 } 81467 81468 _runCallbacksIfReady() { 81469 if (this.isStable()) { 81470 // Schedules the call backs in a new frame so that it is always async. 81471 scheduleMicroTask(() => { 81472 while (this._callbacks.length !== 0) { 81473 let cb = this._callbacks.pop(); 81474 81475 clearTimeout(cb.timeoutId); 81476 cb.doneCb(this._didWork); 81477 } 81478 81479 this._didWork = false; 81480 }); 81481 } else { 81482 // Still not stable, send updates. 81483 let pending = this.getPendingTasks(); 81484 this._callbacks = this._callbacks.filter(cb => { 81485 if (cb.updateCb && cb.updateCb(pending)) { 81486 clearTimeout(cb.timeoutId); 81487 return false; 81488 } 81489 81490 return true; 81491 }); 81492 this._didWork = true; 81493 } 81494 } 81495 81496 getPendingTasks() { 81497 if (!this.taskTrackingZone) { 81498 return []; 81499 } // Copy the tasks data so that we don't leak tasks. 81500 81501 81502 return this.taskTrackingZone.macroTasks.map(t => { 81503 return { 81504 source: t.source, 81505 // From TaskTrackingZone: 81506 // https://github.com/angular/zone.js/blob/master/lib/zone-spec/task-tracking.ts#L40 81507 creationLocation: t.creationLocation, 81508 data: t.data 81509 }; 81510 }); 81511 } 81512 81513 addCallback(cb, timeout, updateCb) { 81514 let timeoutId = -1; 81515 81516 if (timeout && timeout > 0) { 81517 timeoutId = setTimeout(() => { 81518 this._callbacks = this._callbacks.filter(cb => cb.timeoutId !== timeoutId); 81519 cb(this._didWork, this.getPendingTasks()); 81520 }, timeout); 81521 } 81522 81523 this._callbacks.push({ 81524 doneCb: cb,
81525 timeoutId: timeoutId, 81526 updateCb: updateCb 81527 }); 81528 } 81529 /** 81530 * Wait for the application to be stable with a timeout. If the timeout is reached before that 81531 * happens, the callback receives a list of the macro tasks that were pending, otherwise null. 81532 * 81533 * @param doneCb The callback to invoke when Angular is stable or the timeout expires 81534 * whichever comes first. 81535 * @param timeout Optional. The maximum time to wait for Angular to become stable. If not 81536 * specified, whenStable() will wait forever. 81537 * @param updateCb Optional. If specified, this callback will be invoked whenever the set of 81538 * pending macrotasks changes. If this callback returns true doneCb will not be invoked 81539 * and no further updates will be issued. 81540 */ 81541 81542 81543 whenStable(doneCb, timeout, updateCb) { 81544 if (updateCb && !this.taskTrackingZone) { 81545 throw new Error('Task tracking zone is required when passing an update callback to ' + 'whenStable(). Is "zone.js/plugins/task-tracking" loaded?'); 81546 } // These arguments are 'Function' above to keep the public API simple. 81547 81548 81549 this.addCallback(doneCb, timeout, updateCb); 81550 81551 this._runCallbacksIfReady(); 81552 } 81553 /** 81554 * Get the number of pending requests 81555 * @deprecated pending requests are now tracked with zones 81556 */ 81557 81558 81559 getPendingRequestCount() { 81560 return this._pendingCount; 81561 } 81562 /** 81563 * Registers an application with a testability hook so that it can be tracked. 81564 * @param token token of application, root element 81565 * 81566 * @internal 81567 */ 81568 81569 81570 registerApplication(token) { 81571 this.registry.registerApplication(token, this); 81572 } 81573 /** 81574 * Unregisters an application. 81575 * @param token token of application, root element 81576 * 81577 * @internal 81578 */ 81579 81580 81581 unregisterApplication(token) { 81582 this.registry.unregisterApplication(token); 81583 } 81584 /** 81585 * Find providers by name 81586 * @param using The root element to search from 81587 * @param provider The name of binding variable 81588 * @param exactMatch Whether using exactMatch 81589 */ 81590 81591 81592 findProviders(using, provider, exactMatch) { 81593 // TODO(juliemr): implement. 81594 return []; 81595 } 81596 81597} 81598 81599Testability.ɵfac = function Testability_Factory(t) { 81600 return new (t || Testability)(ɵɵinject(NgZone), ɵɵinject(TestabilityRegistry), ɵɵinject(TESTABILITY_GETTER)); 81601}; 81602 81603Testability.ɵprov = /*@__PURE__*/ɵɵdefineInjectable({ 81604 token: Testability, 81605 factory: Testability.ɵfac 81606}); 81607 81608(function () { 81609 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Testability, [{ 81610 type: Injectable 81611 }], function () { 81612 return [{ 81613 type: NgZone 81614 }, { 81615 type: TestabilityRegistry 81616 }, { 81617 type: undefined, 81618 decorators: [{ 81619 type: Inject, 81620 args: [TESTABILITY_GETTER] 81621 }] 81622 }]; 81623 }, null); 81624})(); 81625/** 81626 * A global registry of {@link Testability} instances for specific elements. 81627 * @publicApi 81628 */ 81629 81630 81631class TestabilityRegistry { 81632 constructor() { 81633 /** @internal */ 81634 this._applications = new Map(); 81635 } 81636 /** 81637 * Registers an application with a testability hook so that it can be tracked 81638 * @param token token of application, root element 81639 * @param testability Testability hook 81640 */ 81641 81642 81643 registerApplication(token, testability) { 81644 this._applications.set(token, testability); 81645 } 81646 /** 81647 * Unregisters an application. 81648 * @param token token of application, root element 81649 */ 81650 81651 81652 unregisterApplication(token) { 81653 this._applications.delete(token); 81654 } 81655 /** 81656 * Unregisters all applications 81657 */ 81658 81659 81660 unregisterAllApplications() { 81661 this._applications.clear(); 81662 } 81663 /** 81664 * Get a testability hook associated with the application 81665 * @param elem root element 81666 */ 81667 81668 81669 getTestability(elem) { 81670 return this._applications.get(elem) || null; 81671 } 81672 /** 81673 * Get all registered testabilities 81674 */ 81675 81676 81677 getAllTestabilities() { 81678 return Array.from(this._applications.values()); 81679 } 81680 /** 81681 * Get all registered applications(root elements) 81682 */ 81683 81684 81685 getAllRootElements() { 81686 return Array.from(this._applications.keys()); 81687 } 81688 /** 81689 * Find testability of a node in the Tree 81690 * @param elem node 81691 * @param findInAncestors whether finding testability in ancestors if testability was not found in 81692 * current node 81693 */ 81694 81695 81696 findTestabilityInTree(elem, findInAncestors = true) { 81697 return _testabilityGetter?.findTestabilityInTree(this, elem, findInAncestors) ?? null; 81698 } 81699 81700} 81701 81702TestabilityRegistry.ɵfac = function TestabilityRegistry_Factory(t) { 81703 return new (t || TestabilityRegistry)(); 81704}; 81705 81706TestabilityRegistry.ɵprov = /*@__PURE__*/ɵɵdefineInjectable({ 81707 token: TestabilityRegistry, 81708 factory: TestabilityRegistry.ɵfac, 81709 providedIn: 'platform' 81710}); 81711 81712(function () { 81713 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(TestabilityRegistry, [{ 81714 type: Injectable, 81715 args: [{ 81716 providedIn: 'platform' 81717 }] 81718 }], null, null); 81719})(); 81720/** 81721 * Set the {@link GetTestability} implementation used by the Angular testing framework. 81722 * @publicApi 81723 */ 81724 81725 81726function setTestabilityGetter(getter) { 81727 _testabilityGetter = getter; 81728} 81729 81730let _testabilityGetter; 81731/** 81732 * @license 81733 * Copyright Google LLC All Rights Reserved. 81734 * 81735 * Use of this source code is governed by an MIT-style license that can be 81736 * found in the LICENSE file at https://angular.io/license 81737 */ 81738 81739 81740let _platformInjector = null; 81741/** 81742 * Internal token to indicate whether having multiple bootstrapped platform should be allowed (only 81743 * one bootstrapped platform is allowed by default). This token helps to support SSR scenarios. 81744 */ 81745 81746const ALLOW_MULTIPLE_PLATFORMS = new InjectionToken('AllowMultipleToken'); 81747/** 81748 * Internal token that allows to register extra callbacks that should be invoked during the 81749 * `PlatformRef.destroy` operation. This token is needed to avoid a direct reference to the 81750 * `PlatformRef` class (i.e. register the callback via `PlatformRef.onDestroy`), thus making the 81751 * entire class tree-shakeable. 81752 */ 81753 81754const PLATFORM_DESTROY_LISTENERS = new InjectionToken('PlatformDestroyListeners'); 81755const NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode; 81756 81757function compileNgModuleFactory(injector, options, moduleType) { 81758 ngDevMode && assertNgModuleType(moduleType); 81759 const moduleFactory = new NgModuleFactory(moduleType); // All of the logic below is irrelevant for AOT-compiled code. 81760 81761 if (typeof ngJitMode !== 'undefined' && !ngJitMode) { 81762 return Promise.resolve(moduleFactory); 81763 } 81764 81765 const compilerOptions = injector.get(COMPILER_OPTIONS, []).concat(options); // Configure the compiler to use the provided options. This call may fail when multiple modules 81766 // are bootstrapped with incompatible options, as a component can only be compiled according to 81767 // a single set of options. 81768 81769 setJitOptions({ 81770 defaultEncapsulation: _lastDefined(compilerOptions.map(opts => opts.defaultEncapsulation)),
81771 preserveWhitespaces: _lastDefined(compilerOptions.map(opts => opts.preserveWhitespaces)) 81772 }); 81773 81774 if (isComponentResourceResolutionQueueEmpty()) { 81775 return Promise.resolve(moduleFactory); 81776 } 81777 81778 const compilerProviders = _mergeArrays(compilerOptions.map(o => o.providers)); // In case there are no compiler providers, we just return the module factory as 81779 // there won't be any resource loader. This can happen with Ivy, because AOT compiled 81780 // modules can be still passed through "bootstrapModule". In that case we shouldn't 81781 // unnecessarily require the JIT compiler. 81782 81783 81784 if (compilerProviders.length === 0) { 81785 return Promise.resolve(moduleFactory); 81786 } 81787 81788 const compiler = getCompilerFacade({ 81789 usage: 0 81790 /* JitCompilerUsage.Decorator */ 81791 , 81792 kind: 'NgModule', 81793 type: moduleType 81794 }); 81795 const compilerInjector = Injector.create({ 81796 providers: compilerProviders 81797 }); 81798 const resourceLoader = compilerInjector.get(compiler.ResourceLoader); // The resource loader can also return a string while the "resolveComponentResources" 81799 // always expects a promise. Therefore we need to wrap the returned value in a promise. 81800 81801 return resolveComponentResources(url => Promise.resolve(resourceLoader.get(url))).then(() => moduleFactory); 81802} 81803 81804function publishDefaultGlobalUtils() { 81805 ngDevMode && publishDefaultGlobalUtils$1(); 81806} 81807 81808function isBoundToModule(cf) { 81809 return cf.isBoundToModule; 81810} 81811/** 81812 * A token for third-party components that can register themselves with NgProbe. 81813 * 81814 * @publicApi 81815 */ 81816 81817 81818class NgProbeToken { 81819 constructor(name, token) { 81820 this.name = name; 81821 this.token = token; 81822 } 81823 81824} 81825/** 81826 * Creates a platform. 81827 * Platforms must be created on launch using this function. 81828 * 81829 * @publicApi 81830 */ 81831 81832 81833function createPlatform(injector) { 81834 if (_platformInjector && !_platformInjector.get(ALLOW_MULTIPLE_PLATFORMS, false)) { 81835 throw new RuntimeError(400 81836 /* RuntimeErrorCode.MULTIPLE_PLATFORMS */ 81837 , ngDevMode && 'There can be only one platform. Destroy the previous one to create a new one.'); 81838 } 81839 81840 publishDefaultGlobalUtils(); 81841 _platformInjector = injector; 81842 const platform = injector.get(PlatformRef); 81843 runPlatformInitializers(injector); 81844 return platform; 81845} 81846/** 81847 * The goal of this function is to bootstrap a platform injector, 81848 * but avoid referencing `PlatformRef` class. 81849 * This function is needed for bootstrapping a Standalone Component. 81850 */ 81851 81852 81853function createOrReusePlatformInjector(providers = []) { 81854 // If a platform injector already exists, it means that the platform 81855 // is already bootstrapped and no additional actions are required. 81856 if (_platformInjector) return _platformInjector; // Otherwise, setup a new platform injector and run platform initializers. 81857 81858 const injector = createPlatformInjector(providers); 81859 _platformInjector = injector; 81860 publishDefaultGlobalUtils(); 81861 runPlatformInitializers(injector); 81862 return injector; 81863} 81864 81865function runPlatformInitializers(injector) { 81866 const inits = injector.get(PLATFORM_INITIALIZER, null); 81867 81868 if (inits) { 81869 inits.forEach(init => init()); 81870 } 81871} 81872/** 81873 * Internal create application API that implements the core application creation logic and optional 81874 * bootstrap logic. 81875 * 81876 * Platforms (such as `platform-browser`) may require different set of application and platform 81877 * providers for an application to function correctly. As a result, platforms may use this function 81878 * internally and supply the necessary providers during the bootstrap, while exposing 81879 * platform-specific APIs as a part of their public API. 81880 * 81881 * @returns A promise that returns an `ApplicationRef` instance once resolved. 81882 */ 81883 81884 81885function internalCreateApplication(config) { 81886 const { 81887 rootComponent, 81888 appProviders, 81889 platformProviders 81890 } = config; 81891 81892 if (NG_DEV_MODE && rootComponent !== undefined) { 81893 assertStandaloneComponentType(rootComponent); 81894 } 81895 81896 const platformInjector = createOrReusePlatformInjector(platformProviders); 81897 const ngZone = getNgZone('zone.js', getNgZoneOptions()); 81898 return ngZone.run(() => { 81899 // Create root application injector based on a set of providers configured at the platform 81900 // bootstrap level as well as providers passed to the bootstrap call by a user. 81901 const allAppProviders = [{ 81902 provide: NgZone, 81903 useValue: ngZone 81904 }
vendor: 3,812 bytes, lines 81904-82021
81904, ...(appProviders || []) // 81905 ]; 81906 const envInjector = createEnvironmentInjector(allAppProviders, platformInjector, 'Environment Injector'); 81907 const exceptionHandler = envInjector.get(ErrorHandler, null); 81908 81909 if (NG_DEV_MODE && !exceptionHandler) { 81910 throw new RuntimeError(402 81911 /* RuntimeErrorCode.ERROR_HANDLER_NOT_FOUND */ 81912 , 'No `ErrorHandler` found in the Dependency Injection tree.'); 81913 } 81914 81915 let onErrorSubscription; 81916 ngZone.runOutsideAngular(() => { 81917 onErrorSubscription = ngZone.onError.subscribe({ 81918 next: error => { 81919 exceptionHandler.handleError(error); 81920 } 81921 }); 81922 }); // If the whole platform is destroyed, invoke the `destroy` method 81923 // for all bootstrapped applications as well. 81924 81925 const destroyListener = () => envInjector.destroy(); 81926 81927 const onPlatformDestroyListeners = platformInjector.get(PLATFORM_DESTROY_LISTENERS); 81928 onPlatformDestroyListeners.add(destroyListener); 81929 envInjector.onDestroy(() => { 81930 onErrorSubscription.unsubscribe(); 81931 onPlatformDestroyListeners.delete(destroyListener); 81932 }); 81933 return _callAndReportToErrorHandler(exceptionHandler, ngZone, () => { 81934 const initStatus = envInjector.get(ApplicationInitStatus); 81935 initStatus.runInitializers(); 81936 return initStatus.donePromise.then(() => { 81937 const localeId = envInjector.get(LOCALE_ID, DEFAULT_LOCALE_ID); 81938 setLocaleId(localeId || DEFAULT_LOCALE_ID); 81939 const appRef = envInjector.get(ApplicationRef); 81940 81941 if (rootComponent !== undefined) { 81942 appRef.bootstrap(rootComponent); 81943 } 81944 81945 return appRef; 81946 }); 81947 }); 81948 }); 81949} 81950/** 81951 * Creates a factory for a platform. Can be used to provide or override `Providers` specific to 81952 * your application's runtime needs, such as `PLATFORM_INITIALIZER` and `PLATFORM_ID`. 81953 * @param parentPlatformFactory Another platform factory to modify. Allows you to compose factories 81954 * to build up configurations that might be required by different libraries or parts of the 81955 * application. 81956 * @param name Identifies the new platform factory. 81957 * @param providers A set of dependency providers for platforms created with the new factory. 81958 * 81959 * @publicApi 81960 */ 81961 81962 81963function createPlatformFactory(parentPlatformFactory, name, providers = []) { 81964 const desc = `Platform: ${name}`; 81965 const marker = new InjectionToken(desc); 81966 return (extraProviders = []) => { 81967 let platform = getPlatform(); 81968 81969 if (!platform || platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) { 81970 const platformProviders = [...providers, ...extraProviders, { 81971 provide: marker, 81972 useValue: true 81973 }]; 81974 81975 if (parentPlatformFactory) { 81976 parentPlatformFactory(platformProviders); 81977 } else { 81978 createPlatform(createPlatformInjector(platformProviders, desc)); 81979 } 81980 } 81981 81982 return assertPlatform(marker); 81983 }; 81984} 81985/** 81986 * Checks that there is currently a platform that contains the given token as a provider. 81987 * 81988 * @publicApi 81989 */ 81990 81991 81992function assertPlatform(requiredToken) { 81993 const platform = getPlatform(); 81994 81995 if (!platform) { 81996 throw new RuntimeError(401 81997 /* RuntimeErrorCode.PLATFORM_NOT_FOUND */ 81998 , ngDevMode && 'No platform exists!'); 81999 } 82000 82001 if ((typeof ngDevMode === 'undefined' || ngDevMode) && !platform.injector.get(requiredToken, null)) { 82002 throw new RuntimeError(400 82003 /* RuntimeErrorCode.MULTIPLE_PLATFORMS */ 82004 , 'A platform with a different configuration has been created. Please destroy it first.'); 82005 } 82006 82007 return platform; 82008} 82009/** 82010 * Helper function to create an instance of a platform injector (that maintains the 'platform' 82011 * scope). 82012 */ 82013 82014 82015function createPlatformInjector(providers = [], name) { 82016 return Injector.create({ 82017 name, 82018 providers: [{ 82019 provide: INJECTOR_SCOPE, 82020 useValue: 'platform' 82021 }, {
82022 provide: PLATFORM_DESTROY_LISTENERS, 82023 useValue: new Set([() => _platformInjector = null]) 82024 }, ...providers] 82025 }); 82026} 82027/** 82028 * Destroys the current Angular platform and all Angular applications on the page. 82029 * Destroys all modules and listeners registered with the platform. 82030 * 82031 * @publicApi 82032 */ 82033 82034 82035function destroyPlatform() { 82036 getPlatform()?.destroy(); 82037} 82038/** 82039 * Returns the current platform. 82040 * 82041 * @publicApi 82042 */ 82043 82044 82045function getPlatform() { 82046 return _platformInjector?.get(PlatformRef) ?? null; 82047} 82048/** 82049 * The Angular platform is the entry point for Angular on a web page. 82050 * Each page has exactly one platform. Services (such as reflection) which are common 82051 * to every Angular application running on the page are bound in its scope. 82052 * A page's platform is initialized implicitly when a platform is created using a platform 82053 * factory such as `PlatformBrowser`, or explicitly by calling the `createPlatform()` function. 82054 * 82055 * @publicApi 82056 */ 82057 82058 82059class PlatformRef { 82060 /** @internal */ 82061 constructor(_injector) { 82062 this._injector = _injector; 82063 this._modules = []; 82064 this._destroyListeners = []; 82065 this._destroyed = false; 82066 } 82067 /** 82068 * Creates an instance of an `@NgModule` for the given platform. 82069 * 82070 * @deprecated Passing NgModule factories as the `PlatformRef.bootstrapModuleFactory` function 82071 * argument is deprecated. Use the `PlatformRef.bootstrapModule` API instead. 82072 */ 82073 82074 82075 bootstrapModuleFactory(moduleFactory, options) { 82076 // Note: We need to create the NgZone _before_ we instantiate the module, 82077 // as instantiating the module creates some providers eagerly. 82078 // So we create a mini parent injector that just contains the new NgZone and 82079 // pass that as parent to the NgModuleFactory. 82080 const ngZone = getNgZone(options?.ngZone, getNgZoneOptions(options)); 82081 const providers = [{ 82082 provide: NgZone, 82083 useValue: ngZone 82084 }]; // Note: Create ngZoneInjector within ngZone.run so that all of the instantiated services are 82085 // created within the Angular zone 82086 // Do not try to replace ngZone.run with ApplicationRef#run because ApplicationRef would then be 82087 // created outside of the Angular zone. 82088 82089 return ngZone.run(() => { 82090 const ngZoneInjector = Injector.create({ 82091 providers: providers, 82092 parent: this.injector, 82093 name: moduleFactory.moduleType.name 82094 }); 82095 const moduleRef = moduleFactory.create(ngZoneInjector); 82096 const exceptionHandler = moduleRef.injector.get(ErrorHandler, null); 82097 82098 if (!exceptionHandler) { 82099 throw new RuntimeError(402 82100 /* RuntimeErrorCode.ERROR_HANDLER_NOT_FOUND */ 82101 , ngDevMode && 'No ErrorHandler. Is platform module (BrowserModule) included?'); 82102 } 82103 82104 ngZone.runOutsideAngular(() => { 82105 const subscription = ngZone.onError.subscribe({ 82106 next: error => { 82107 exceptionHandler.handleError(error); 82108 } 82109 }); 82110 moduleRef.onDestroy(() => { 82111 remove(this._modules, moduleRef); 82112 subscription.unsubscribe(); 82113 }); 82114 }); 82115 return _callAndReportToErrorHandler(exceptionHandler, ngZone, () => { 82116 const initStatus = moduleRef.injector.get(ApplicationInitStatus); 82117 initStatus.runInitializers(); 82118 return initStatus.donePromise.then(() => { 82119 // If the `LOCALE_ID` provider is defined at bootstrap then we set the value for ivy 82120 const localeId = moduleRef.injector.get(LOCALE_ID, DEFAULT_LOCALE_ID); 82121 setLocaleId(localeId || DEFAULT_LOCALE_ID); 82122 82123 this._moduleDoBootstrap(moduleRef); 82124 82125 return moduleRef; 82126 }); 82127 }); 82128 }); 82129 } 82130 /** 82131 * Creates an instance of an `@NgModule` for a given platform. 82132 * 82133 * @usageNotes 82134 * ### Simple Example 82135 * 82136 * ```typescript 82137 * @NgModule({ 82138 * imports: [BrowserModule] 82139 * }) 82140 * class MyModule {} 82141 * 82142 * let moduleRef = platformBrowser().bootstrapModule(MyModule); 82143 * ``` 82144 * 82145 */ 82146 82147 82148 bootstrapModule(moduleType, compilerOptions = []) { 82149 const options = optionsReducer({}, compilerOptions); 82150 return compileNgModuleFactory(this.injector, options, moduleType).then(moduleFactory => this.bootstrapModuleFactory(moduleFactory, options)); 82151 } 82152 82153 _moduleDoBootstrap(moduleRef) { 82154 const appRef = moduleRef.injector.get(ApplicationRef); 82155 82156 if (moduleRef._bootstrapComponents.length > 0) {
82157 moduleRef._bootstrapComponents.forEach(f => appRef.bootstrap(f)); 82158 } else if (moduleRef.instance.ngDoBootstrap) { 82159 moduleRef.instance.ngDoBootstrap(appRef); 82160 } else { 82161 throw new RuntimeError(403 82162 /* RuntimeErrorCode.BOOTSTRAP_COMPONENTS_NOT_FOUND */ 82163 , ngDevMode && `The module ${stringify(moduleRef.instance.constructor)} was bootstrapped, ` + `but it does not declare "@NgModule.bootstrap" components nor a "ngDoBootstrap" method. ` + `Please define one of these.`); 82164 } 82165 82166 this._modules.push(moduleRef); 82167 } 82168 /** 82169 * Registers a listener to be called when the platform is destroyed. 82170 */ 82171 82172 82173 onDestroy(callback) { 82174 this._destroyListeners.push(callback); 82175 } 82176 /** 82177 * Retrieves the platform {@link Injector}, which is the parent injector for 82178 * every Angular application on the page and provides singleton providers. 82179 */ 82180 82181 82182 get injector() { 82183 return this._injector; 82184 } 82185 /** 82186 * Destroys the current Angular platform and all Angular applications on the page. 82187 * Destroys all modules and listeners registered with the platform. 82188 */ 82189 82190 82191 destroy() { 82192 if (this._destroyed) { 82193 throw new RuntimeError(404 82194 /* RuntimeErrorCode.PLATFORM_ALREADY_DESTROYED */ 82195 , ngDevMode && 'The platform has already been destroyed!'); 82196 } 82197 82198 this._modules.slice().forEach(module => module.destroy()); 82199 82200 this._destroyListeners.forEach(listener => listener()); 82201 82202 const destroyListeners = this._injector.get(PLATFORM_DESTROY_LISTENERS, null); 82203 82204 if (destroyListeners) { 82205 destroyListeners.forEach(listener => listener()); 82206 destroyListeners.clear(); 82207 } 82208 82209 this._destroyed = true; 82210 } 82211 /** 82212 * Indicates whether this instance was destroyed. 82213 */ 82214 82215 82216 get destroyed() { 82217 return this._destroyed; 82218 } 82219 82220} 82221 82222PlatformRef.ɵfac = function PlatformRef_Factory(t) { 82223 return new (t || PlatformRef)(ɵɵinject(Injector)); 82224}; 82225 82226PlatformRef.ɵprov = /*@__PURE__*/ɵɵdefineInjectable({ 82227 token: PlatformRef, 82228 factory: PlatformRef.ɵfac, 82229 providedIn: 'platform' 82230}); 82231 82232(function () { 82233 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PlatformRef, [{ 82234 type: Injectable, 82235 args: [{ 82236 providedIn: 'platform' 82237 }] 82238 }], function () { 82239 return [{ 82240 type: Injector 82241 }]; 82242 }, null); 82243})(); // Transforms a set of `BootstrapOptions` (supported by the NgModule-based bootstrap APIs) -> 82244// `NgZoneOptions` that are recognized by the NgZone constructor. Passing no options will result in 82245// a set of default options returned. 82246 82247 82248function getNgZoneOptions(options) { 82249 return { 82250 enableLongStackTrace: typeof ngDevMode === 'undefined' ? false : !!ngDevMode, 82251 shouldCoalesceEventChangeDetection: !!(options && options.ngZoneEventCoalescing) || false, 82252 shouldCoalesceRunChangeDetection: !!(options && options.ngZoneRunCoalescing) || false 82253 }; 82254} 82255 82256function getNgZone(ngZoneToUse, options) { 82257 let ngZone; 82258 82259 if (ngZoneToUse === 'noop') { 82260 ngZone = new NoopNgZone(); 82261 } else { 82262 ngZone = (ngZoneToUse === 'zone.js' ? undefined : ngZoneToUse) || new NgZone(options); 82263 } 82264 82265 return ngZone; 82266} 82267 82268function _callAndReportToErrorHandler(errorHandler, ngZone, callback) { 82269 try { 82270 const result = callback(); 82271 82272 if (isPromise(result)) { 82273 return result.catch(e => { 82274 ngZone.runOutsideAngular(() => errorHandler.handleError(e)); // rethrow as the exception handler might not do it 82275 82276 throw e; 82277 }); 82278 } 82279 82280 return result; 82281 } catch (e) { 82282 ngZone.runOutsideAngular(() => errorHandler.handleError(e)); // rethrow as the exception handler might not do it 82283 82284 throw e; 82285 } 82286} 82287 82288function optionsReducer(dst, objs) { 82289 if (Array.isArray(objs)) { 82290 dst = objs.reduce(optionsReducer, dst); 82291 } else { 82292 dst = { ...dst, 82293 ...objs 82294 }; 82295 } 82296 82297 return dst; 82298} 82299/** 82300 * A reference to an Angular application running on a page. 82301 * 82302 * @usageNotes 82303 * 82304 * {@a is-stable-examples} 82305 * ### isStable examples and caveats 82306 * 82307 * Note two important points about `isStable`, demonstrated in the examples below: 82308 * - the application will never be stable if you start any kind 82309 * of recurrent asynchronous task when the application starts 82310 * (for example for a polling process, started with a `setInterval`, a `setTimeout` 82311 * or using RxJS operators like `interval`); 82312 * - the `isStable` Observable runs outside of the Angular zone. 82313 * 82314 * Let's imagine that you start a recurrent task 82315 * (here incrementing a counter, using RxJS `interval`), 82316 * and at the same time subscribe to `isStable`. 82317 * 82318 * ``` 82319 * constructor(appRef: ApplicationRef) { 82320 * appRef.isStable.pipe( 82321 * filter(stable => stable) 82322 * ).subscribe(() => console.log('App is stable now'); 82323 * interval(1000).subscribe(counter => console.log(counter)); 82324 * } 82325 * ``` 82326 * In this example, `isStable` will never emit `true`, 82327 * and the trace "App is stable now" will never get logged. 82328 * 82329 * If you want to execute something when the app is stable, 82330 * you have to wait for the application to be stable 82331 * before starting your polling process. 82332 * 82333 * ``` 82334 * constructor(appRef: ApplicationRef) { 82335 * appRef.isStable.pipe( 82336 * first(stable => stable), 82337 * tap(stable => console.log('App is stable now')), 82338 * switchMap(() => interval(1000)) 82339 * ).subscribe(counter => console.log(counter)); 82340 * } 82341 * ``` 82342 * In this example, the trace "App is stable now" will be logged 82343 * and then the counter starts incrementing every second. 82344 *
82345 * Note also that this Observable runs outside of the Angular zone, 82346 * which means that the code in the subscription 82347 * to this Observable will not trigger the change detection. 82348 * 82349 * Let's imagine that instead of logging the counter value, 82350 * you update a field of your component 82351 * and display it in its template. 82352 * 82353 * ``` 82354 * constructor(appRef: ApplicationRef) { 82355 * appRef.isStable.pipe( 82356 * first(stable => stable), 82357 * switchMap(() => interval(1000)) 82358 * ).subscribe(counter => this.value = counter); 82359 * } 82360 * ``` 82361 * As the `isStable` Observable runs outside the zone, 82362 * the `value` field will be updated properly, 82363 * but the template will not be refreshed! 82364 * 82365 * You'll have to manually trigger the change detection to update the template. 82366 * 82367 * ``` 82368 * constructor(appRef: ApplicationRef, cd: ChangeDetectorRef) { 82369 * appRef.isStable.pipe( 82370 * first(stable => stable), 82371 * switchMap(() => interval(1000)) 82372 * ).subscribe(counter => { 82373 * this.value = counter; 82374 * cd.detectChanges(); 82375 * }); 82376 * } 82377 * ``` 82378 * 82379 * Or make the subscription callback run inside the zone. 82380 * 82381 * ``` 82382 * constructor(appRef: ApplicationRef, zone: NgZone) { 82383 * appRef.isStable.pipe( 82384 * first(stable => stable), 82385 * switchMap(() => interval(1000)) 82386 * ).subscribe(counter => zone.run(() => this.value = counter)); 82387 * } 82388 * ``` 82389 * 82390 * @publicApi 82391 */ 82392 82393 82394class ApplicationRef { 82395 /** @internal */ 82396 constructor(_zone, _injector, _exceptionHandler) { 82397 this._zone = _zone; 82398 this._injector = _injector; 82399 this._exceptionHandler = _exceptionHandler; 82400 /** @internal */ 82401 82402 this._bootstrapListeners = []; 82403 this._views = []; 82404 this._runningTick = false; 82405 this._stable = true; 82406 this._destroyed = false; 82407 this._destroyListeners = []; 82408 /** 82409 * Get a list of component types registered to this application. 82410 * This list is populated even before the component is created. 82411 */ 82412 82413 this.componentTypes = []; 82414 /** 82415 * Get a list of components registered to this application. 82416 */ 82417 82418 this.components = []; 82419 this._onMicrotaskEmptySubscription = this._zone.onMicrotaskEmpty.subscribe({ 82420 next: () => { 82421 this._zone.run(() => { 82422 this.tick(); 82423 }); 82424 } 82425 }); 82426 const isCurrentlyStable = new rxjs__WEBPACK_IMPORTED_MODULE_2__.Observable(observer => { 82427 this._stable = this._zone.isStable && !this._zone.hasPendingMacrotasks && !this._zone.hasPendingMicrotasks; 82428 82429 this._zone.runOutsideAngular(() => { 82430 observer.next(this._stable); 82431 observer.complete(); 82432 }); 82433 }); 82434 const isStable = new rxjs__WEBPACK_IMPORTED_MODULE_2__.Observable(observer => { 82435 // Create the subscription to onStable outside the Angular Zone so that 82436 // the callback is run outside the Angular Zone. 82437 let stableSub; 82438 82439 this._zone.runOutsideAngular(() => { 82440 stableSub = this._zone.onStable.subscribe(() => { 82441 NgZone.assertNotInAngularZone(); // Check whether there are no pending macro/micro tasks in the next tick 82442 // to allow for NgZone to update the state. 82443 82444 scheduleMicroTask(() => { 82445 if (!this._stable && !this._zone.hasPendingMacrotasks && !this._zone.hasPendingMicrotasks) { 82446 this._stable = true; 82447 observer.next(true); 82448 } 82449 }); 82450 }); 82451 }); 82452 82453 const unstableSub = this._zone.onUnstable.subscribe(() => { 82454 NgZone.assertInAngularZone(); 82455 82456 if (this._stable) { 82457 this._stable = false; 82458 82459 this._zone.runOutsideAngular(() => { 82460 observer.next(false); 82461 }); 82462 } 82463 }); 82464 82465 return () => { 82466 stableSub.unsubscribe(); 82467 unstableSub.unsubscribe(); 82468 }; 82469 }); 82470 this.isStable = (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.merge)(isCurrentlyStable, isStable.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.share)())); 82471 } 82472 /** 82473 * Indicates whether this instance was destroyed. 82474 */ 82475 82476 82477 get destroyed() { 82478 return this._destroyed; 82479 } 82480 /** 82481 * The `EnvironmentInjector` used to create this application. 82482 */ 82483 82484 82485 get injector() { 82486 return this._injector; 82487 } 82488 /** 82489 * Bootstrap a component onto the element identified by its selector or, optionally, to a 82490 * specified element. 82491 * 82492 * @usageNotes 82493 * ### Bootstrap process 82494 * 82495 * When bootstrapping a component, Angular mounts it onto a target DOM element 82496 * and kicks off automatic change detection. The target DOM element can be 82497 * provided using the `rootSelectorOrNode` argument. 82498 * 82499 * If the target DOM element is not provided, Angular tries to find one on a page 82500 * using the `selector` of the component that is being bootstrapped 82501 * (first matched element is used). 82502 * 82503 * ### Example 82504 * 82505 * Generally, we define the component to bootstrap in the `bootstrap` array of `NgModule`, 82506 * but it requires us to know the component while writing the application code. 82507 * 82508 * Imagine a situation where we have to wait for an API call to decide about the component to 82509 * bootstrap. We can use the `ngDoBootstrap` hook of the `NgModule` and call this method to 82510 * dynamically bootstrap a component. 82511 * 82512 * {@example core/ts/platform/platform.ts region='componentSelector'} 82513 *
82514 * Optionally, a component can be mounted onto a DOM element that does not match the 82515 * selector of the bootstrapped component. 82516 * 82517 * In the following example, we are providing a CSS selector to match the target element. 82518 * 82519 * {@example core/ts/platform/platform.ts region='cssSelector'} 82520 * 82521 * While in this example, we are providing reference to a DOM node. 82522 * 82523 * {@example core/ts/platform/platform.ts region='domNode'} 82524 */ 82525 82526 82527 bootstrap(componentOrFactory, rootSelectorOrNode) { 82528 NG_DEV_MODE && this.warnIfDestroyed(); 82529 const isComponentFactory = componentOrFactory instanceof ComponentFactory$1; 82530 82531 const initStatus = this._injector.get(ApplicationInitStatus); 82532 82533 if (!initStatus.done) { 82534 const standalone = !isComponentFactory && isStandalone(componentOrFactory); 82535 const errorMessage = 'Cannot bootstrap as there are still asynchronous initializers running.' + (standalone ? '' : ' Bootstrap components in the `ngDoBootstrap` method of the root module.'); 82536 throw new RuntimeError(405 82537 /* RuntimeErrorCode.ASYNC_INITIALIZERS_STILL_RUNNING */ 82538 , NG_DEV_MODE && errorMessage); 82539 } 82540 82541 let componentFactory; 82542 82543 if (isComponentFactory) { 82544 componentFactory = componentOrFactory; 82545 } else { 82546 const resolver = this._injector.get(ComponentFactoryResolver$1); 82547 82548 componentFactory = resolver.resolveComponentFactory(componentOrFactory); 82549 } 82550 82551 this.componentTypes.push(componentFactory.componentType); // Create a factory associated with the current module if it's not bound to some other 82552 82553 const ngModule = isBoundToModule(componentFactory) ? undefined : this._injector.get(NgModuleRef$1); 82554 const selectorOrNode = rootSelectorOrNode || componentFactory.selector; 82555 const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule); 82556 const nativeElement = compRef.location.nativeElement; 82557 const testability = compRef.injector.get(TESTABILITY, null); 82558 testability?.registerApplication(nativeElement); 82559 compRef.onDestroy(() => { 82560 this.detachView(compRef.hostView); 82561 remove(this.components, compRef); 82562 testability?.unregisterApplication(nativeElement); 82563 }); 82564 82565 this._loadComponent(compRef); 82566 82567 if (typeof ngDevMode === 'undefined' || ngDevMode) { 82568 const _console = this._injector.get(Console); 82569 82570 _console.log(`Angular is running in development mode. Call enableProdMode() to enable production mode.`); 82571 } 82572 82573 return compRef; 82574 } 82575 /** 82576 * Invoke this method to explicitly process change detection and its side-effects. 82577 * 82578 * In development mode, `tick()` also performs a second change detection cycle to ensure that no 82579 * further changes are detected. If additional changes are picked up during this second cycle, 82580 * bindings in the app have side-effects that cannot be resolved in a single change detection 82581 * pass. 82582 * In this case, Angular throws an error, since an Angular application can only have one change 82583 * detection pass during which all change detection must complete. 82584 */ 82585 82586 82587 tick() { 82588 NG_DEV_MODE && this.warnIfDestroyed(); 82589 82590 if (this._runningTick) { 82591 throw new RuntimeError(101 82592 /* RuntimeErrorCode.RECURSIVE_APPLICATION_REF_TICK */ 82593 , ngDevMode && 'ApplicationRef.tick is called recursively'); 82594 } 82595 82596 try { 82597 this._runningTick = true; 82598 82599 for (let view of this._views) { 82600 view.detectChanges(); 82601 } 82602 82603 if (typeof ngDevMode === 'undefined' || ngDevMode) { 82604 for (let view of this._views) { 82605 view.checkNoChanges(); 82606 } 82607 } 82608 } catch (e) { 82609 // Attention: Don't rethrow as it could cancel subscriptions to Observables! 82610 this._zone.runOutsideAngular(() => this._exceptionHandler.handleError(e)); 82611 } finally { 82612 this._runningTick = false; 82613 } 82614 } 82615 /** 82616 * Attaches a view so that it will be dirty checked. 82617 * The view will be automatically detached when it is destroyed. 82618 * This will throw if the view is already attached to a ViewContainer. 82619 */ 82620 82621 82622 attachView(viewRef) { 82623 NG_DEV_MODE && this.warnIfDestroyed(); 82624 const view = viewRef; 82625 82626 this._views.push(view); 82627 82628 view.attachToAppRef(this); 82629 } 82630 /** 82631 * Detaches a view from dirty checking again. 82632 */ 82633 82634 82635 detachView(viewRef) { 82636 NG_DEV_MODE && this.warnIfDestroyed(); 82637 const view = viewRef; 82638 remove(this._views, view); 82639 view.detachFromAppRef(); 82640 } 82641 82642 _loadComponent(componentRef) { 82643 this.attachView(componentRef.hostView); 82644 this.tick(); 82645 this.components.push(componentRef); // Get the listeners lazily to prevent DI cycles. 82646 82647 const listeners = this._injector.get(APP_BOOTSTRAP_LISTENER, []).concat(this._bootstrapListeners); 82648
82649 listeners.forEach(listener => listener(componentRef)); 82650 } 82651 /** @internal */ 82652 82653 82654 ngOnDestroy() { 82655 if (this._destroyed) return; 82656 82657 try { 82658 // Call all the lifecycle hooks. 82659 this._destroyListeners.forEach(listener => listener()); // Destroy all registered views. 82660 82661 82662 this._views.slice().forEach(view => view.destroy()); 82663 82664 this._onMicrotaskEmptySubscription.unsubscribe(); 82665 } finally { 82666 // Indicate that this instance is destroyed. 82667 this._destroyed = true; // Release all references. 82668 82669 this._views = []; 82670 this._bootstrapListeners = []; 82671 this._destroyListeners = []; 82672 } 82673 } 82674 /** 82675 * Registers a listener to be called when an instance is destroyed. 82676 * 82677 * @param callback A callback function to add as a listener. 82678 * @returns A function which unregisters a listener. 82679 * 82680 * @internal 82681 */ 82682 82683 82684 onDestroy(callback) { 82685 NG_DEV_MODE && this.warnIfDestroyed(); 82686 82687 this._destroyListeners.push(callback); 82688 82689 return () => remove(this._destroyListeners, callback); 82690 } 82691 /** 82692 * Destroys an Angular application represented by this `ApplicationRef`. Calling this function 82693 * will destroy the associated environment injectors as well as all the bootstrapped components 82694 * with their views. 82695 */ 82696 82697 82698 destroy() { 82699 if (this._destroyed) { 82700 throw new RuntimeError(406 82701 /* RuntimeErrorCode.APPLICATION_REF_ALREADY_DESTROYED */ 82702 , ngDevMode && 'This instance of the `ApplicationRef` has already been destroyed.'); 82703 } 82704 82705 const injector = this._injector; // Check that this injector instance supports destroy operation. 82706 82707 if (injector.destroy && !injector.destroyed) { 82708 // Destroying an underlying injector will trigger the `ngOnDestroy` lifecycle 82709 // hook, which invokes the remaining cleanup actions. 82710 injector.destroy(); 82711 } 82712 } 82713 /** 82714 * Returns the number of attached views. 82715 */ 82716 82717 82718 get viewCount() { 82719 return this._views.length; 82720 } 82721 82722 warnIfDestroyed() { 82723 if (NG_DEV_MODE && this._destroyed) { 82724 console.warn(formatRuntimeError(406 82725 /* RuntimeErrorCode.APPLICATION_REF_ALREADY_DESTROYED */ 82726 , 'This instance of the `ApplicationRef` has already been destroyed.')); 82727 } 82728 } 82729 82730} 82731 82732ApplicationRef.ɵfac = function ApplicationRef_Factory(t) { 82733 return new (t || ApplicationRef)(ɵɵinject(NgZone), ɵɵinject(EnvironmentInjector), ɵɵinject(ErrorHandler)); 82734}; 82735 82736ApplicationRef.ɵprov = /*@__PURE__*/ɵɵdefineInjectable({ 82737 token: ApplicationRef, 82738 factory: ApplicationRef.ɵfac, 82739 providedIn: 'root' 82740}); 82741 82742(function () { 82743 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationRef, [{ 82744 type: Injectable, 82745 args: [{ 82746 providedIn: 'root' 82747 }] 82748 }], function () { 82749 return [{ 82750 type: NgZone 82751 }, { 82752 type: EnvironmentInjector 82753 }, { 82754 type: ErrorHandler 82755 }]; 82756 }, null); 82757})(); 82758 82759function remove(list, el) { 82760 const index = list.indexOf(el); 82761 82762 if (index > -1) { 82763 list.splice(index, 1); 82764 } 82765} 82766 82767function _lastDefined(args) { 82768 for (let i = args.length - 1; i >= 0; i--) { 82769 if (args[i] !== undefined) { 82770 return args[i]; 82771 } 82772 } 82773 82774 return undefined; 82775} 82776 82777function _mergeArrays(parts) { 82778 const result = []; 82779 parts.forEach(part => part && result.push(...part)); 82780 return result; 82781} 82782/** 82783 * @license 82784 * Copyright Google LLC All Rights Reserved. 82785 * 82786 * Use of this source code is governed by an MIT-style license that can be 82787 * found in the LICENSE file at https://angular.io/license 82788 */ 82789 82790/** 82791 * This file is used to control if the default rendering pipeline should be `ViewEngine` or `Ivy`. 82792 * 82793 * For more information on how to run and debug tests with either Ivy or View Engine (legacy), 82794 * please see [BAZEL.md](./docs/BAZEL.md). 82795 */ 82796 82797 82798let _devMode = true; 82799let _runModeLocked = false; 82800/** 82801 * Returns whether Angular is in development mode. After called once, 82802 * the value is locked and won't change any more. 82803 * 82804 * By default, this is true, unless a user calls `enableProdMode` before calling this. 82805 * 82806 * @publicApi 82807 */ 82808 82809function isDevMode() { 82810 _runModeLocked = true; 82811 return _devMode; 82812} 82813/** 82814 * Disable Angular's development mode, which turns off assertions and other 82815 * checks within the framework. 82816 * 82817 * One important assertion this disables verifies that a change detection pass 82818 * does not result in additional changes to any bindings (also known as 82819 * unidirectional data flow). 82820 * 82821 * @publicApi 82822 */ 82823 82824 82825function enableProdMode() { 82826 if (_runModeLocked) { 82827 throw new Error('Cannot enable prod mode after platform setup.'); 82828 } // The below check is there so when ngDevMode is set via terser 82829 // `global['ngDevMode'] = false;` is also dropped. 82830 82831 82832 if (typeof ngDevMode === 'undefined' || ngDevMode) { 82833 _global['ngDevMode'] = false;
82834 } 82835 82836 _devMode = false; 82837} 82838/** 82839 * @license 82840 * Copyright Google LLC All Rights Reserved. 82841 * 82842 * Use of this source code is governed by an MIT-style license that can be 82843 * found in the LICENSE file at https://angular.io/license 82844 */ 82845 82846/** 82847 * @license 82848 * Copyright Google LLC All Rights Reserved. 82849 * 82850 * Use of this source code is governed by an MIT-style license that can be 82851 * found in the LICENSE file at https://angular.io/license 82852 */ 82853 82854/** 82855 * @license 82856 * Copyright Google LLC All Rights Reserved. 82857 * 82858 * Use of this source code is governed by an MIT-style license that can be 82859 * found in the LICENSE file at https://angular.io/license 82860 */ 82861 82862/** 82863 * Returns the NgModuleFactory with the given id (specified using [@NgModule.id 82864 * field](api/core/NgModule#id)), if it exists and has been loaded. Factories for NgModules that do 82865 * not specify an `id` cannot be retrieved. Throws if an NgModule cannot be found. 82866 * @publicApi 82867 * @deprecated Use `getNgModuleById` instead. 82868 */ 82869 82870 82871function getModuleFactory(id) { 82872 const type = getRegisteredNgModuleType(id); 82873 if (!type) throw noModuleError(id); 82874 return new NgModuleFactory(type); 82875} 82876/** 82877 * Returns the NgModule class with the given id (specified using [@NgModule.id 82878 * field](api/core/NgModule#id)), if it exists and has been loaded. Classes for NgModules that do 82879 * not specify an `id` cannot be retrieved. Throws if an NgModule cannot be found. 82880 * @publicApi 82881 */ 82882 82883 82884function getNgModuleById(id) { 82885 const type = getRegisteredNgModuleType(id); 82886 if (!type) throw noModuleError(id); 82887 return type; 82888} 82889 82890function noModuleError(id) { 82891 return new Error(`No module with ID ${id} loaded`); 82892} 82893/** 82894 * @license 82895 * Copyright Google LLC All Rights Reserved. 82896 * 82897 * Use of this source code is governed by an MIT-style license that can be 82898 * found in the LICENSE file at https://angular.io/license 82899 */ 82900 82901/** 82902 * Base class that provides change detection functionality. 82903 * A change-detection tree collects all views that are to be checked for changes. 82904 * Use the methods to add and remove views from the tree, initiate change-detection, 82905 * and explicitly mark views as _dirty_, meaning that they have changed and need to be re-rendered. 82906 * 82907 * @see [Using change detection hooks](guide/lifecycle-hooks#using-change-detection-hooks) 82908 * @see [Defining custom change detection](guide/lifecycle-hooks#defining-custom-change-detection) 82909 * 82910 * @usageNotes 82911 * 82912 * The following examples demonstrate how to modify default change-detection behavior 82913 * to perform explicit detection when needed. 82914 * 82915 * ### Use `markForCheck()` with `CheckOnce` strategy 82916 * 82917 * The following example sets the `OnPush` change-detection strategy for a component 82918 * (`CheckOnce`, rather than the default `CheckAlways`), then forces a second check 82919 * after an interval. See [live demo](https://plnkr.co/edit/GC512b?p=preview). 82920 * 82921 * <code-example path="core/ts/change_detect/change-detection.ts" 82922 * region="mark-for-check"></code-example> 82923 * 82924 * ### Detach change detector to limit how often check occurs 82925 * 82926 * The following example defines a component with a large list of read-only data 82927 * that is expected to change constantly, many times per second. 82928 * To improve performance, we want to check and update the list 82929 * less often than the changes actually occur. To do that, we detach 82930 * the component's change detector and perform an explicit local check every five seconds. 82931 * 82932 * <code-example path="core/ts/change_detect/change-detection.ts" region="detach"></code-example> 82933 * 82934 * 82935 * ### Reattaching a detached component 82936 * 82937 * The following example creates a component displaying live data. 82938 * The component detaches its change detector from the main change detector tree 82939 * when the `live` property is set to false, and reattaches it when the property 82940 * becomes true. 82941 * 82942 * <code-example path="core/ts/change_detect/change-detection.ts" region="reattach"></code-example> 82943 * 82944 * @publicApi 82945 */ 82946 82947 82948class ChangeDetectorRef {} 82949/** 82950 * @internal 82951 * @nocollapse 82952 */ 82953 82954 82955ChangeDetectorRef.__NG_ELEMENT_ID__ = injectChangeDetectorRef; 82956/** Returns a ChangeDetectorRef (a.k.a. a ViewRef) */ 82957 82958function injectChangeDetectorRef(flags) { 82959 return createViewRef(getCurrentTNode(), getLView(), (flags & 16 82960 /* InternalInjectFlags.ForPipe */ 82961 ) === 16 82962 /* InternalInjectFlags.ForPipe */ 82963 ); 82964} 82965/** 82966 * Creates a ViewRef and stores it on the injector as ChangeDetectorRef (public alias). 82967 * 82968 * @param tNode The node that is requesting a ChangeDetectorRef 82969 * @param lView The view to which the node belongs 82970 * @param isPipe Whether the view is being injected into a pipe. 82971 * @returns The ChangeDetectorRef to use 82972 */ 82973 82974 82975function createViewRef(tNode, lView, isPipe) { 82976 if (isComponentHost(tNode) && !isPipe) { 82977 // The LView represents the location where the component is declared. 82978 // Instead we want the LView for the component View and so we need to look it up. 82979 const componentView = getComponentLViewByIndex(tNode.index, lView); // look down 82980 82981 return new ViewRef$1(componentView, componentView); 82982 } else if (tNode.type & (3 82983 /* TNodeType.AnyRNode */ 82984 | 12 82985 /* TNodeType.AnyContainer */ 82986 | 32 82987 /* TNodeType.Icu */ 82988 )) { 82989 // The LView represents the location where the injection is requested from. 82990 // We need to locate the containing LView (in case where the `lView` is an embedded view) 82991 const hostComponentView = lView[DECLARATION_COMPONENT_VIEW]; // look up 82992 82993 return new ViewRef$1(hostComponentView, lView); 82994 } 82995 82996 return null; 82997} 82998/** 82999 * @license 83000 * Copyright Google LLC All Rights Reserved. 83001 * 83002 * Use of this source code is governed by an MIT-style license that can be 83003 * found in the LICENSE file at https://angular.io/license 83004 */ 83005 83006/** 83007 * Represents an Angular [view](guide/glossary#view "Definition"). 83008 * 83009 * @see {@link ChangeDetectorRef#usage-notes Change detection usage} 83010 * 83011 * @publicApi 83012 */ 83013 83014 83015class ViewRef extends ChangeDetectorRef {} 83016/** 83017 * Represents an Angular [view](guide/glossary#view) in a view container. 83018 * An [embedded view](guide/glossary#view-tree) can be referenced from a component 83019 * other than the hosting component whose template defines it, or it can be defined 83020 * independently by a `TemplateRef`. 83021 * 83022 * Properties of elements in a view can change, but the structure (number and order) of elements in 83023 * a view cannot. Change the structure of elements by inserting, moving, or 83024 * removing nested views in a view container. 83025 * 83026 * @see `ViewContainerRef` 83027 * 83028 * @usageNotes 83029 * 83030 * The following template breaks down into two separate `TemplateRef` instances, 83031 * an outer one and an inner one. 83032 * 83033 * ``` 83034 * Count: {{items.length}} 83035 * <ul> 83036 * <li *ngFor="let item of items">{{item}}</li> 83037 * </ul> 83038 * ``` 83039 * 83040 * This is the outer `TemplateRef`: 83041 * 83042 * ``` 83043 * Count: {{items.length}} 83044 * <ul> 83045 * <ng-template ngFor let-item [ngForOf]="items"></ng-template> 83046 * </ul> 83047 * ``` 83048 * 83049 * This is the inner `TemplateRef`: 83050 * 83051 * ``` 83052 * <li>{{item}}</li> 83053 * ``` 83054 *
83055 * The outer and inner `TemplateRef` instances are assembled into views as follows: 83056 * 83057 * ``` 83058 * <!-- ViewRef: outer-0 --> 83059 * Count: 2 83060 * <ul> 83061 * <ng-template view-container-ref></ng-template> 83062 * <!-- ViewRef: inner-1 --><li>first</li><!-- /ViewRef: inner-1 --> 83063 * <!-- ViewRef: inner-2 --><li>second</li><!-- /ViewRef: inner-2 --> 83064 * </ul> 83065 * <!-- /ViewRef: outer-0 --> 83066 * ``` 83067 * @publicApi 83068 */ 83069 83070 83071class EmbeddedViewRef extends ViewRef {} 83072/** 83073 * @license 83074 * Copyright Google LLC All Rights Reserved. 83075 * 83076 * Use of this source code is governed by an MIT-style license that can be 83077 * found in the LICENSE file at https://angular.io/license 83078 */ 83079 83080/** 83081 * @license 83082 * Copyright Google LLC All Rights Reserved. 83083 * 83084 * Use of this source code is governed by an MIT-style license that can be 83085 * found in the LICENSE file at https://angular.io/license 83086 */ 83087// This file exists for easily patching NgModuleFactoryLoader in g3 83088 83089 83090var ng_module_factory_loader_impl = {}; 83091/** 83092 * @license 83093 * Copyright Google LLC All Rights Reserved. 83094 * 83095 * Use of this source code is governed by an MIT-style license that can be 83096 * found in the LICENSE file at https://angular.io/license 83097 */ 83098 83099/** 83100 * @publicApi 83101 */ 83102 83103class DebugEventListener { 83104 constructor(name, callback) { 83105 this.name = name; 83106 this.callback = callback; 83107 } 83108 83109} 83110/** 83111 * @publicApi 83112 */ 83113 83114 83115function asNativeElements(debugEls) { 83116 return debugEls.map(el => el.nativeElement); 83117} 83118/** 83119 * @publicApi 83120 */ 83121 83122 83123class DebugNode { 83124 constructor(nativeNode) { 83125 this.nativeNode = nativeNode; 83126 } 83127 /** 83128 * The `DebugElement` parent. Will be `null` if this is the root element. 83129 */ 83130 83131 83132 get parent() { 83133 const parent = this.nativeNode.parentNode; 83134 return parent ? new DebugElement(parent) : null; 83135 } 83136 /** 83137 * The host dependency injector. For example, the root element's component instance injector. 83138 */ 83139 83140 83141 get injector() { 83142 return getInjector(this.nativeNode); 83143 } 83144 /** 83145 * The element's own component instance, if it has one. 83146 */ 83147 83148 83149 get componentInstance() { 83150 const nativeElement = this.nativeNode; 83151 return nativeElement && (getComponent(nativeElement) || getOwningComponent(nativeElement)); 83152 } 83153 /** 83154 * An object that provides parent context for this element. Often an ancestor component instance 83155 * that governs this element. 83156 * 83157 * When an element is repeated within *ngFor, the context is an `NgForOf` whose `$implicit` 83158 * property is the value of the row instance value. For example, the `hero` in `*ngFor="let hero 83159 * of heroes"`. 83160 */ 83161 83162 83163 get context() { 83164 return getComponent(this.nativeNode) || getContext(this.nativeNode); 83165 } 83166 /** 83167 * The callbacks attached to the component's @Output properties and/or the element's event 83168 * properties. 83169 */ 83170 83171 83172 get listeners() { 83173 return getListeners(this.nativeNode).filter(listener => listener.type === 'dom'); 83174 } 83175 /** 83176 * Dictionary of objects associated with template local variables (e.g. #foo), keyed by the local 83177 * variable name. 83178 */ 83179 83180 83181 get references() { 83182 return getLocalRefs(this.nativeNode); 83183 } 83184 /** 83185 * This component's injector lookup tokens. Includes the component itself plus the tokens that the 83186 * component lists in its providers metadata. 83187 */ 83188 83189 83190 get providerTokens() { 83191 return getInjectionTokens(this.nativeNode); 83192 } 83193 83194} 83195/** 83196 * @publicApi 83197 * 83198 * @see [Component testing scenarios](guide/testing-components-scenarios) 83199 * @see [Basics of testing components](guide/testing-components-basics) 83200 * @see [Testing utility APIs](guide/testing-utility-apis) 83201 */ 83202 83203 83204class DebugElement extends DebugNode { 83205 constructor(nativeNode) { 83206 ngDevMode && assertDomNode(nativeNode); 83207 super(nativeNode); 83208 } 83209 /** 83210 * The underlying DOM element at the root of the component. 83211 */ 83212 83213 83214 get nativeElement() { 83215 return this.nativeNode.nodeType == Node.ELEMENT_NODE ? this.nativeNode : null; 83216 } 83217 /** 83218 * The element tag name, if it is an element. 83219 */ 83220 83221 83222 get name() { 83223 const context = getLContext(this.nativeNode); 83224 const lView = context ? context.lView : null; 83225 83226 if (lView !== null) { 83227 const tData = lView[TVIEW].data; 83228 const tNode = tData[context.nodeIndex]; 83229 return tNode.value; 83230 } else { 83231 return this.nativeNode.nodeName; 83232 } 83233 } 83234 /** 83235 * Gets a map of property names to property values for an element. 83236 * 83237 * This map includes: 83238 * - Regular property bindings (e.g. `[id]="id"`) 83239 * - Host property bindings (e.g. `host: { '[id]': "id" }`) 83240 * - Interpolated property bindings (e.g. `id="{{ value }}") 83241 * 83242 * It does not include: 83243 * - input property bindings (e.g. `[myCustomInput]="value"`) 83244 * - attribute bindings (e.g. `[attr.role]="menu"`) 83245 */ 83246 83247 83248 get properties() { 83249 const context = getLContext(this.nativeNode); 83250 const lView = context ? context.lView : null; 83251 83252 if (lView === null) { 83253 return {}; 83254 } 83255 83256 const tData = lView[TVIEW].data; 83257 const tNode = tData[context.nodeIndex]; 83258 const properties = {}; // Collect properties from the DOM. 83259 83260 copyDomProperties(this.nativeElement, properties); // Collect properties from the bindings. This is needed for animation renderer which has 83261 // synthetic properties which don't get reflected into the DOM. 83262
83263 collectPropertyBindings(properties, tNode, lView, tData); 83264 return properties; 83265 } 83266 /** 83267 * A map of attribute names to attribute values for an element. 83268 */ 83269 83270 83271 get attributes() { 83272 const attributes = {}; 83273 const element = this.nativeElement; 83274 83275 if (!element) { 83276 return attributes; 83277 } 83278 83279 const context = getLContext(element); 83280 const lView = context ? context.lView : null; 83281 83282 if (lView === null) { 83283 return {}; 83284 } 83285 83286 const tNodeAttrs = lView[TVIEW].data[context.nodeIndex].attrs; 83287 const lowercaseTNodeAttrs = []; // For debug nodes we take the element's attribute directly from the DOM since it allows us 83288 // to account for ones that weren't set via bindings (e.g. ViewEngine keeps track of the ones 83289 // that are set through `Renderer2`). The problem is that the browser will lowercase all names, 83290 // however since we have the attributes already on the TNode, we can preserve the case by going 83291 // through them once, adding them to the `attributes` map and putting their lower-cased name 83292 // into an array. Afterwards when we're going through the native DOM attributes, we can check 83293 // whether we haven't run into an attribute already through the TNode. 83294 83295 if (tNodeAttrs) { 83296 let i = 0; 83297 83298 while (i < tNodeAttrs.length) { 83299 const attrName = tNodeAttrs[i]; // Stop as soon as we hit a marker. We only care about the regular attributes. Everything 83300 // else will be handled below when we read the final attributes off the DOM. 83301 83302 if (typeof attrName !== 'string') break; 83303 const attrValue = tNodeAttrs[i + 1]; 83304 attributes[attrName] = attrValue; 83305 lowercaseTNodeAttrs.push(attrName.toLowerCase()); 83306 i += 2; 83307 } 83308 } 83309 83310 const eAttrs = element.attributes; 83311 83312 for (let i = 0; i < eAttrs.length; i++) { 83313 const attr = eAttrs[i]; 83314 const lowercaseName = attr.name.toLowerCase(); // Make sure that we don't assign the same attribute both in its 83315 // case-sensitive form and the lower-cased one from the browser. 83316 83317 if (lowercaseTNodeAttrs.indexOf(lowercaseName) === -1) { 83318 // Save the lowercase name to align the behavior between browsers. 83319 // IE preserves the case, while all other browser convert it to lower case. 83320 attributes[lowercaseName] = attr.value; 83321 } 83322 } 83323 83324 return attributes; 83325 } 83326 /** 83327 * The inline styles of the DOM element. 83328 * 83329 * Will be `null` if there is no `style` property on the underlying DOM element. 83330 * 83331 * @see [ElementCSSInlineStyle](https://developer.mozilla.org/en-US/docs/Web/API/ElementCSSInlineStyle/style) 83332 */ 83333 83334 83335 get styles() { 83336 if (this.nativeElement && this.nativeElement.style) { 83337 return this.nativeElement.style; 83338 } 83339 83340 return {}; 83341 } 83342 /** 83343 * A map containing the class names on the element as keys. 83344 * 83345 * This map is derived from the `className` property of the DOM element. 83346 * 83347 * Note: The values of this object will always be `true`. The class key will not appear in the KV 83348 * object if it does not exist on the element. 83349 * 83350 * @see [Element.className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) 83351 */ 83352 83353 83354 get classes() { 83355 const result = {}; 83356 const element = this.nativeElement; // SVG elements return an `SVGAnimatedString` instead of a plain string for the `className`. 83357 83358 const className = element.className; 83359 const classes = typeof className !== 'string' ? className.baseVal.split(' ') : className.split(' '); 83360 classes.forEach(value => result[value] = true); 83361 return result; 83362 } 83363 /** 83364 * The `childNodes` of the DOM element as a `DebugNode` array. 83365 * 83366 * @see [Node.childNodes](https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes) 83367 */ 83368 83369 83370 get childNodes() { 83371 const childNodes = this.nativeNode.childNodes; 83372 const children = []; 83373 83374 for (let i = 0; i < childNodes.length; i++) { 83375 const element = childNodes[i]; 83376 children.push(getDebugNode(element)); 83377 } 83378 83379 return children; 83380 } 83381 /** 83382 * The immediate `DebugElement` children. Walk the tree by descending through `children`. 83383 */ 83384 83385 83386 get children() { 83387 const nativeElement = this.nativeElement; 83388 if (!nativeElement) return []; 83389 const childNodes = nativeElement.children; 83390 const children = []; 83391 83392 for (let i = 0; i < childNodes.length; i++) { 83393 const element = childNodes[i]; 83394 children.push(getDebugNode(element)); 83395 } 83396 83397 return children; 83398 } 83399 /** 83400 * @returns the first `DebugElement` that matches the predicate at any depth in the subtree. 83401 */ 83402 83403 83404 query(predicate) { 83405 const results = this.queryAll(predicate); 83406 return results[0] || null; 83407 } 83408 /** 83409 * @returns All `DebugElement` matches for the predicate at any depth in the subtree. 83410 */ 83411 83412 83413 queryAll(predicate) { 83414 const matches = []; 83415 83416 _queryAll(this, predicate, matches, true); 83417 83418 return matches; 83419 } 83420 /** 83421 * @returns All `DebugNode` matches for the predicate at any depth in the subtree. 83422 */ 83423 83424 83425 queryAllNodes(predicate) { 83426 const matches = []; 83427 83428 _queryAll(this, predicate, matches, false); 83429 83430 return matches; 83431 } 83432 /** 83433 * Triggers the event by its name if there is a corresponding listener in the element's 83434 * `listeners` collection. 83435 * 83436 * If the event lacks a listener or there's some other problem, consider 83437 * calling `nativeElement.dispatchEvent(eventObject)`. 83438 * 83439 * @param eventName The name of the event to trigger 83440 * @param eventObj The _event object_ expected by the handler 83441 * 83442 * @see [Testing components scenarios](guide/testing-components-scenarios#trigger-event-handler) 83443 */ 83444 83445 83446 triggerEventHandler(eventName, eventObj) { 83447 const node = this.nativeNode; 83448 const invokedListeners = [];
83449 this.listeners.forEach(listener => { 83450 if (listener.name === eventName) { 83451 const callback = listener.callback; 83452 callback.call(node, eventObj); 83453 invokedListeners.push(callback); 83454 } 83455 }); // We need to check whether `eventListeners` exists, because it's something 83456 // that Zone.js only adds to `EventTarget` in browser environments. 83457 83458 if (typeof node.eventListeners === 'function') { 83459 // Note that in Ivy we wrap event listeners with a call to `event.preventDefault` in some 83460 // cases. We use '__ngUnwrap__' as a special token that gives us access to the actual event 83461 // listener. 83462 node.eventListeners(eventName).forEach(listener => { 83463 // In order to ensure that we can detect the special __ngUnwrap__ token described above, we 83464 // use `toString` on the listener and see if it contains the token. We use this approach to 83465 // ensure that it still worked with compiled code since it cannot remove or rename string 83466 // literals. We also considered using a special function name (i.e. if(listener.name === 83467 // special)) but that was more cumbersome and we were also concerned the compiled code could 83468 // strip the name, turning the condition in to ("" === "") and always returning true. 83469 if (listener.toString().indexOf('__ngUnwrap__') !== -1) { 83470 const unwrappedListener = listener('__ngUnwrap__'); 83471 return invokedListeners.indexOf(unwrappedListener) === -1 && unwrappedListener.call(node, eventObj); 83472 } 83473 }); 83474 } 83475 } 83476 83477} 83478 83479function copyDomProperties(element, properties) { 83480 if (element) { 83481 // Skip own properties (as those are patched) 83482 let obj = Object.getPrototypeOf(element); 83483 const NodePrototype = Node.prototype; 83484 83485 while (obj !== null && obj !== NodePrototype) { 83486 const descriptors = Object.getOwnPropertyDescriptors(obj); 83487 83488 for (let key in descriptors) { 83489 if (!key.startsWith('__') && !key.startsWith('on')) { 83490 // don't include properties starting with `__` and `on`. 83491 // `__` are patched values which should not be included. 83492 // `on` are listeners which also should not be included. 83493 const value = element[key]; 83494 83495 if (isPrimitiveValue(value)) { 83496 properties[key] = value; 83497 } 83498 } 83499 } 83500 83501 obj = Object.getPrototypeOf(obj); 83502 } 83503 } 83504} 83505 83506function isPrimitiveValue(value) { 83507 return typeof value === 'string' || typeof value === 'boolean' || typeof value === 'number' || value === null; 83508} 83509 83510function _queryAll(parentElement, predicate, matches, elementsOnly) { 83511 const context = getLContext(parentElement.nativeNode); 83512 const lView = context ? context.lView : null; 83513 83514 if (lView !== null) { 83515 const parentTNode = lView[TVIEW].data[context.nodeIndex]; 83516 83517 _queryNodeChildren(parentTNode, lView, predicate, matches, elementsOnly, parentElement.nativeNode); 83518 } else { 83519 // If the context is null, then `parentElement` was either created with Renderer2 or native DOM 83520 // APIs. 83521 _queryNativeNodeDescendants(parentElement.nativeNode, predicate, matches, elementsOnly); 83522 } 83523} 83524/** 83525 * Recursively match the current TNode against the predicate, and goes on with the next ones. 83526 * 83527 * @param tNode the current TNode 83528 * @param lView the LView of this TNode 83529 * @param predicate the predicate to match 83530 * @param matches the list of positive matches 83531 * @param elementsOnly whether only elements should be searched 83532 * @param rootNativeNode the root native node on which predicate should not be matched 83533 */ 83534 83535 83536function _queryNodeChildren(tNode, lView, predicate, matches, elementsOnly, rootNativeNode) { 83537 ngDevMode && assertTNodeForLView(tNode, lView); 83538 const nativeNode = getNativeByTNodeOrNull(tNode, lView); // For each type of TNode, specific logic is executed. 83539 83540 if (tNode.type & (3 83541 /* TNodeType.AnyRNode */ 83542 | 8 83543 /* TNodeType.ElementContainer */ 83544 )) { 83545 // Case 1: the TNode is an element 83546 // The native node has to be checked. 83547 _addQueryMatch(nativeNode, predicate, matches, elementsOnly, rootNativeNode); 83548 83549 if (isComponentHost(tNode)) { 83550 // If the element is the host of a component, then all nodes in its view have to be processed. 83551 // Note: the component's content (tNode.child) will be processed from the insertion points. 83552 const componentView = getComponentLViewByIndex(tNode.index, lView); 83553 83554 if (componentView && componentView[TVIEW].firstChild) { 83555 _queryNodeChildren(componentView[TVIEW].firstChild, componentView, predicate, matches, elementsOnly, rootNativeNode); 83556 } 83557 } else { 83558 if (tNode.child) { 83559 // Otherwise, its children have to be processed. 83560 _queryNodeChildren(tNode.child, lView, predicate, matches, elementsOnly, rootNativeNode); 83561 } // We also have to query the DOM directly in order to catch elements inserted through 83562 // Renderer2. Note that this is __not__ optimal, because we're walking similar trees multiple 83563 // times. ViewEngine could do it more efficiently, because all the insertions go through 83564 // Renderer2, however that's not the case in Ivy. This approach is being used because: 83565 // 1. Matching the ViewEngine behavior would mean potentially introducing a dependency 83566 // from `Renderer2` to Ivy which could bring Ivy code into ViewEngine. 83567 // 2. It allows us to capture nodes that were inserted directly via the DOM. 83568 83569 83570 nativeNode && _queryNativeNodeDescendants(nativeNode, predicate, matches, elementsOnly); 83571 } // In all cases, if a dynamic container exists for this node, each view inside it has to be 83572 // processed. 83573 83574 83575 const nodeOrContainer = lView[tNode.index]; 83576 83577 if (isLContainer(nodeOrContainer)) { 83578 _queryNodeChildrenInContainer(nodeOrContainer, predicate, matches, elementsOnly, rootNativeNode); 83579 } 83580 } else if (tNode.type & 4 83581 /* TNodeType.Container */ 83582 ) { 83583 // Case 2: the TNode is a container 83584 // The native node has to be checked. 83585 const lContainer = lView[tNode.index]; 83586 83587 _addQueryMatch(lContainer[NATIVE], predicate, matches, elementsOnly, rootNativeNode); // Each view inside the container has to be processed. 83588 83589 83590 _queryNodeChildrenInContainer(lContainer, predicate, matches, elementsOnly, rootNativeNode); 83591 } else if (tNode.type & 16 83592 /* TNodeType.Projection */ 83593 ) { 83594 // Case 3: the TNode is a projection insertion point (i.e. a <ng-content>). 83595 // The nodes projected at this location all need to be processed. 83596 const componentView = lView[DECLARATION_COMPONENT_VIEW]; 83597 const componentHost = componentView[T_HOST]; 83598 const head = componentHost.projection[tNode.projection]; 83599 83600 if (Array.isArray(head)) { 83601 for (let nativeNode of head) { 83602 _addQueryMatch(nativeNode, predicate, matches, elementsOnly, rootNativeNode); 83603 } 83604 } else if (head) { 83605 const nextLView = componentView[PARENT]; 83606 const nextTNode = nextLView[TVIEW].data[head.index]; 83607 83608 _queryNodeChildren(nextTNode, nextLView, predicate, matches, elementsOnly, rootNativeNode); 83609 } 83610 } else if (tNode.child) { 83611 // Case 4: the TNode is a view. 83612 _queryNodeChildren(tNode.child, lView, predicate, matches, elementsOnly, rootNativeNode); 83613 } // We don't want to go to the next sibling of the root node. 83614 83615 83616 if (rootNativeNode !== nativeNode) { 83617 // To determine the next node to be processed, we need to use the next or the projectionNext 83618 // link, depending on whether the current node has been projected. 83619 const nextTNode = tNode.flags & 4 83620 /* TNodeFlags.isProjected */ 83621 ? tNode.projectionNext : tNode.next; 83622 83623 if (nextTNode) { 83624 _queryNodeChildren(nextTNode, lView, predicate, matches, elementsOnly, rootNativeNode); 83625 } 83626 } 83627} 83628/** 83629 * Process all TNodes in a given container. 83630 * 83631 * @param lContainer the container to be processed 83632 * @param predicate the predicate to match 83633 * @param matches the list of positive matches 83634 * @param elementsOnly whether only elements should be searched 83635 * @param rootNativeNode the root native node on which predicate should not be matched 83636 */ 83637 83638 83639function _queryNodeChildrenInContainer(lContainer, predicate, matches, elementsOnly, rootNativeNode) { 83640 for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) { 83641 const childView = lContainer[i]; 83642 const firstChild = childView[TVIEW].firstChild; 83643 83644 if (firstChild) { 83645 _queryNodeChildren(firstChild, childView, predicate, matches, elementsOnly, rootNativeNode); 83646 } 83647 } 83648} 83649/** 83650 * Match the current native node against the predicate. 83651 * 83652 * @param nativeNode the current native node 83653 * @param predicate the predicate to match 83654 * @param matches the list of positive matches 83655 * @param elementsOnly whether only elements should be searched 83656 * @param rootNativeNode the root native node on which predicate should not be matched 83657 */ 83658 83659 83660function _addQueryMatch(nativeNode, predicate, matches, elementsOnly, rootNativeNode) { 83661 if (rootNativeNode !== nativeNode) { 83662 const debugNode = getDebugNode(nativeNode); 83663 83664 if (!debugNode) { 83665 return; 83666 } // Type of the "predicate and "matches" array are set based on the value of 83667 // the "elementsOnly" parameter. TypeScript is not able to properly infer these 83668 // types with generics, so we manually cast the parameters accordingly. 83669 83670 83671 if (elementsOnly && debugNode instanceof DebugElement && predicate(debugNode) && matches.indexOf(debugNode) === -1) { 83672 matches.push(debugNode); 83673 } else if (!elementsOnly && predicate(debugNode) && matches.indexOf(debugNode) === -1) { 83674 matches.push(debugNode); 83675 } 83676 } 83677} 83678/** 83679 * Match all the descendants of a DOM node against a predicate. 83680 * 83681 * @param nativeNode the current native node 83682 * @param predicate the predicate to match 83683 * @param matches the list where matches are stored 83684 * @param elementsOnly whether only elements should be searched 83685 */ 83686 83687 83688function _queryNativeNodeDescendants(parentNode, predicate, matches, elementsOnly) { 83689 const nodes = parentNode.childNodes; 83690 const length = nodes.length; 83691 83692 for (let i = 0; i < length; i++) { 83693 const node = nodes[i]; 83694 const debugNode = getDebugNode(node); 83695 83696 if (debugNode) { 83697 if (elementsOnly && debugNode instanceof DebugElement && predicate(debugNode) && matches.indexOf(debugNode) === -1) { 83698 matches.push(debugNode); 83699 } else if (!elementsOnly && predicate(debugNode) && matches.indexOf(debugNode) === -1) { 83700 matches.push(debugNode); 83701 } 83702 83703 _queryNativeNodeDescendants(node, predicate, matches, elementsOnly); 83704 } 83705 } 83706} 83707/** 83708 * Iterates through the property bindings for a given node and generates 83709 * a map of property names to values. This map only contains property bindings 83710 * defined in templates, not in host bindings. 83711 */ 83712 83713
83714function collectPropertyBindings(properties, tNode, lView, tData) { 83715 let bindingIndexes = tNode.propertyBindings; 83716 83717 if (bindingIndexes !== null) { 83718 for (let i = 0; i < bindingIndexes.length; i++) { 83719 const bindingIndex = bindingIndexes[i]; 83720 const propMetadata = tData[bindingIndex]; 83721 const metadataParts = propMetadata.split(INTERPOLATION_DELIMITER); 83722 const propertyName = metadataParts[0]; 83723 83724 if (metadataParts.length > 1) { 83725 let value = metadataParts[1]; 83726 83727 for (let j = 1; j < metadataParts.length - 1; j++) { 83728 value += renderStringify(lView[bindingIndex + j - 1]) + metadataParts[j + 1]; 83729 } 83730 83731 properties[propertyName] = value; 83732 } else { 83733 properties[propertyName] = lView[bindingIndex]; 83734 } 83735 } 83736 } 83737} // Need to keep the nodes in a global Map so that multiple angular apps are supported. 83738 83739 83740const _nativeNodeToDebugNode = new Map(); 83741 83742const NG_DEBUG_PROPERTY = '__ng_debug__'; 83743/** 83744 * @publicApi 83745 */ 83746 83747function getDebugNode(nativeNode) { 83748 if (nativeNode instanceof Node) { 83749 if (!nativeNode.hasOwnProperty(NG_DEBUG_PROPERTY)) { 83750 nativeNode[NG_DEBUG_PROPERTY] = nativeNode.nodeType == Node.ELEMENT_NODE ? new DebugElement(nativeNode) : new DebugNode(nativeNode); 83751 } 83752 83753 return nativeNode[NG_DEBUG_PROPERTY]; 83754 } 83755 83756 return null; 83757} // TODO: cleanup all references to this function and remove it. 83758 83759 83760function getDebugNodeR2(_nativeNode) { 83761 return null; 83762} 83763 83764function getAllDebugNodes() { 83765 return Array.from(_nativeNodeToDebugNode.values()); 83766} 83767 83768function indexDebugNode(node) { 83769 _nativeNodeToDebugNode.set(node.nativeNode, node); 83770} 83771 83772function removeDebugNodeFromIndex(node) { 83773 _nativeNodeToDebugNode.delete(node.nativeNode); 83774} 83775/** 83776 * @license 83777 * Copyright Google LLC All Rights Reserved. 83778 * 83779 * Use of this source code is governed by an MIT-style license that can be 83780 * found in the LICENSE file at https://angular.io/license 83781 */ 83782 83783 83784class DefaultIterableDifferFactory { 83785 constructor() {} 83786 83787 supports(obj) { 83788 return isListLikeIterable(obj); 83789 } 83790 83791 create(trackByFn) { 83792 return new DefaultIterableDiffer(trackByFn); 83793 } 83794 83795} 83796 83797const trackByIdentity = (index, item) => item; 83798/** 83799 * @deprecated v4.0.0 - Should not be part of public API. 83800 * @publicApi 83801 */ 83802 83803 83804class DefaultIterableDiffer { 83805 constructor(trackByFn) { 83806 this.length = 0; // Keeps track of the used records at any point in time (during & across `_check()` calls) 83807 83808 this._linkedRecords = null; // Keeps track of the removed records at any point in time during `_check()` calls. 83809 83810 this._unlinkedRecords = null; 83811 this._previousItHead = null; 83812 this._itHead = null; 83813 this._itTail = null; 83814 this._additionsHead = null; 83815 this._additionsTail = null; 83816 this._movesHead = null; 83817 this._movesTail = null; 83818 this._removalsHead = null; 83819 this._removalsTail = null; // Keeps track of records where custom track by is the same, but item identity has changed 83820 83821 this._identityChangesHead = null; 83822 this._identityChangesTail = null; 83823 this._trackByFn = trackByFn || trackByIdentity; 83824 } 83825 83826 forEachItem(fn) { 83827 let record; 83828 83829 for (record = this._itHead; record !== null; record = record._next) { 83830 fn(record); 83831 } 83832 } 83833 83834 forEachOperation(fn) { 83835 let nextIt = this._itHead; 83836 let nextRemove = this._removalsHead; 83837 let addRemoveOffset = 0; 83838 let moveOffsets = null; 83839 83840 while (nextIt || nextRemove) { 83841 // Figure out which is the next record to process 83842 // Order: remove, add, move 83843 const record = !nextRemove || nextIt && nextIt.currentIndex < getPreviousIndex(nextRemove, addRemoveOffset, moveOffsets) ? nextIt : nextRemove; 83844 const adjPreviousIndex = getPreviousIndex(record, addRemoveOffset, moveOffsets); 83845 const currentIndex = record.currentIndex; // consume the item, and adjust the addRemoveOffset and update moveDistance if necessary 83846 83847 if (record === nextRemove) { 83848 addRemoveOffset--; 83849 nextRemove = nextRemove._nextRemoved; 83850 } else { 83851 nextIt = nextIt._next; 83852 83853 if (record.previousIndex == null) { 83854 addRemoveOffset++; 83855 } else { 83856 // INVARIANT: currentIndex < previousIndex 83857 if (!moveOffsets) moveOffsets = []; 83858 const localMovePreviousIndex = adjPreviousIndex - addRemoveOffset; 83859 const localCurrentIndex = currentIndex - addRemoveOffset; 83860 83861 if (localMovePreviousIndex != localCurrentIndex) { 83862 for (let i = 0; i < localMovePreviousIndex; i++) { 83863 const offset = i < moveOffsets.length ? moveOffsets[i] : moveOffsets[i] = 0; 83864 const index = offset + i; 83865 83866 if (localCurrentIndex <= index && index < localMovePreviousIndex) { 83867 moveOffsets[i] = offset + 1; 83868 } 83869 } 83870 83871 const previousIndex = record.previousIndex; 83872 moveOffsets[previousIndex] = localCurrentIndex - localMovePreviousIndex; 83873 } 83874 } 83875 } 83876 83877 if (adjPreviousIndex !== currentIndex) { 83878 fn(record, adjPreviousIndex, currentIndex); 83879 } 83880 } 83881 } 83882 83883 forEachPreviousItem(fn) { 83884 let record; 83885 83886 for (record = this._previousItHead; record !== null; record = record._nextPrevious) { 83887 fn(record); 83888 } 83889 } 83890 83891 forEachAddedItem(fn) { 83892 let record; 83893 83894 for (record = this._additionsHead; record !== null; record = record._nextAdded) { 83895 fn(record); 83896 } 83897 } 83898 83899 forEachMovedItem(fn) { 83900 let record; 83901 83902 for (record = this._movesHead; record !== null; record = record._nextMoved) { 83903 fn(record); 83904 } 83905 } 83906 83907 forEachRemovedItem(fn) { 83908 let record; 83909 83910 for (record = this._removalsHead; record !== null; record = record._nextRemoved) { 83911 fn(record); 83912 } 83913 } 83914 83915 forEachIdentityChange(fn) { 83916 let record; 83917 83918 for (record = this._identityChangesHead; record !== null; record = record._nextIdentityChange) { 83919 fn(record); 83920 } 83921 } 83922 83923 diff(collection) { 83924 if (collection == null) collection = []; 83925 83926 if (!isListLikeIterable(collection)) { 83927 throw new RuntimeError(900 83928 /* RuntimeErrorCode.INVALID_DIFFER_INPUT */
vendor: 5,439 bytes, lines 83929-84094
83929 , ngDevMode && `Error trying to diff '${stringify(collection)}'. Only arrays and iterables are allowed`); 83930 } 83931 83932 if (this.check(collection)) { 83933 return this; 83934 } else { 83935 return null; 83936 } 83937 } 83938 83939 onDestroy() {} 83940 83941 check(collection) { 83942 this._reset(); 83943 83944 let record = this._itHead; 83945 let mayBeDirty = false; 83946 let index; 83947 let item; 83948 let itemTrackBy; 83949 83950 if (Array.isArray(collection)) { 83951 this.length = collection.length; 83952 83953 for (let index = 0; index < this.length; index++) { 83954 item = collection[index]; 83955 itemTrackBy = this._trackByFn(index, item); 83956 83957 if (record === null || !Object.is(record.trackById, itemTrackBy)) { 83958 record = this._mismatch(record, item, itemTrackBy, index); 83959 mayBeDirty = true; 83960 } else { 83961 if (mayBeDirty) { 83962 // TODO(misko): can we limit this to duplicates only? 83963 record = this._verifyReinsertion(record, item, itemTrackBy, index); 83964 } 83965 83966 if (!Object.is(record.item, item)) this._addIdentityChange(record, item); 83967 } 83968 83969 record = record._next; 83970 } 83971 } else { 83972 index = 0; 83973 iterateListLike(collection, item => { 83974 itemTrackBy = this._trackByFn(index, item); 83975 83976 if (record === null || !Object.is(record.trackById, itemTrackBy)) { 83977 record = this._mismatch(record, item, itemTrackBy, index); 83978 mayBeDirty = true; 83979 } else { 83980 if (mayBeDirty) { 83981 // TODO(misko): can we limit this to duplicates only? 83982 record = this._verifyReinsertion(record, item, itemTrackBy, index); 83983 } 83984 83985 if (!Object.is(record.item, item)) this._addIdentityChange(record, item); 83986 } 83987 83988 record = record._next; 83989 index++; 83990 }); 83991 this.length = index; 83992 } 83993 83994 this._truncate(record); 83995 83996 this.collection = collection; 83997 return this.isDirty; 83998 } 83999 /* CollectionChanges is considered dirty if it has any additions, moves, removals, or identity 84000 * changes. 84001 */ 84002 84003 84004 get isDirty() { 84005 return this._additionsHead !== null || this._movesHead !== null || this._removalsHead !== null || this._identityChangesHead !== null; 84006 } 84007 /** 84008 * Reset the state of the change objects to show no changes. This means set previousKey to 84009 * currentKey, and clear all of the queues (additions, moves, removals). 84010 * Set the previousIndexes of moved and added items to their currentIndexes 84011 * Reset the list of additions, moves and removals 84012 * 84013 * @internal 84014 */ 84015 84016 84017 _reset() { 84018 if (this.isDirty) { 84019 let record; 84020 84021 for (record = this._previousItHead = this._itHead; record !== null; record = record._next) { 84022 record._nextPrevious = record._next; 84023 } 84024 84025 for (record = this._additionsHead; record !== null; record = record._nextAdded) { 84026 record.previousIndex = record.currentIndex; 84027 } 84028 84029 this._additionsHead = this._additionsTail = null; 84030 84031 for (record = this._movesHead; record !== null; record = record._nextMoved) { 84032 record.previousIndex = record.currentIndex; 84033 } 84034 84035 this._movesHead = this._movesTail = null; 84036 this._removalsHead = this._removalsTail = null; 84037 this._identityChangesHead = this._identityChangesTail = null; // TODO(vicb): when assert gets supported 84038 // assert(!this.isDirty); 84039 } 84040 } 84041 /** 84042 * This is the core function which handles differences between collections. 84043 * 84044 * - `record` is the record which we saw at this position last time. If null then it is a new 84045 * item. 84046 * - `item` is the current item in the collection 84047 * - `index` is the position of the item in the collection 84048 * 84049 * @internal 84050 */ 84051 84052 84053 _mismatch(record, item, itemTrackBy, index) { 84054 // The previous record after which we will append the current one. 84055 let previousRecord; 84056 84057 if (record === null) { 84058 previousRecord = this._itTail; 84059 } else { 84060 previousRecord = record._prev; // Remove the record from the collection since we know it does not match the item. 84061 84062 this._remove(record); 84063 } // See if we have evicted the item, which used to be at some anterior position of _itHead list. 84064 84065 84066 record = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy, null); 84067 84068 if (record !== null) { 84069 // It is an item which we have evicted earlier: reinsert it back into the list. 84070 // But first we need to check if identity changed, so we can update in view if necessary. 84071 if (!Object.is(record.item, item)) this._addIdentityChange(record, item); 84072 84073 this._reinsertAfter(record, previousRecord, index); 84074 } else { 84075 // Attempt to see if the item is at some posterior position of _itHead list. 84076 record = this._linkedRecords === null ? null : this._linkedRecords.get(itemTrackBy, index); 84077 84078 if (record !== null) { 84079 // We have the item in _itHead at/after `index` position. We need to move it forward in the 84080 // collection. 84081 // But first we need to check if identity changed, so we can update in view if necessary. 84082 if (!Object.is(record.item, item)) this._addIdentityChange(record, item); 84083 84084 this._moveAfter(record, previousRecord, index); 84085 } else { 84086 // It is a new item: add it. 84087 record = this._addAfter(new IterableChangeRecord_(item, itemTrackBy), previousRecord, index); 84088 } 84089 } 84090 84091 return record; 84092 } 84093 /** 84094 * This check is only needed if an array contains duplicates. (Sh
84094ort circuit of nothing dirty) 84095 * 84096 * Use case: `[a, a]` => `[b, a, a]` 84097 * 84098 * If we did not have this check then the insertion of `b` would: 84099 * 1) evict first `a` 84100 * 2) insert `b` at `0` index. 84101 * 3) leave `a` at index `1` as is. <-- this is wrong! 84102 * 3) reinsert `a` at index 2. <-- this is wrong! 84103 * 84104 * The correct behavior is: 84105 * 1) evict first `a` 84106 * 2) insert `b` at `0` index. 84107 * 3) reinsert `a` at index 1. 84108 * 3) move `a` at from `1` to `2`. 84109 * 84110 * 84111 * Double check that we have not evicted a duplicate item. We need to check if the item type may 84112 * have already been removed: 84113 * The insertion of b will evict the first 'a'. If we don't reinsert it now it will be reinserted 84114 * at the end. Which will show up as the two 'a's switching position. This is incorrect, since a 84115 * better way to think of it is as insert of 'b' rather then switch 'a' with 'b' and then add 'a' 84116 * at the end. 84117 * 84118 * @internal 84119 */ 84120 84121 84122 _verifyReinsertion(record, item, itemTrackBy, index) { 84123 let reinsertRecord = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy, null); 84124 84125 if (reinsertRecord !== null) { 84126 record = this._reinsertAfter(reinsertRecord, record._prev, index); 84127 } else if (record.currentIndex != index) { 84128 record.currentIndex = index; 84129 84130 this._addToMoves(record, index); 84131 } 84132 84133 return record; 84134 } 84135 /** 84136 * Get rid of any excess {@link IterableChangeRecord_}s from the previous collection 84137 * 84138 * - `record` The first excess {@link IterableChangeRecord_}. 84139 * 84140 * @internal 84141 */ 84142 84143 84144 _truncate(record) { 84145 // Anything after that needs to be removed; 84146 while (record !== null) { 84147 const nextRecord = record._next; 84148 84149 this._addToRemovals(this._unlink(record)); 84150 84151 record = nextRecord; 84152 } 84153 84154 if (this._unlinkedRecords !== null) { 84155 this._unlinkedRecords.clear(); 84156 } 84157 84158 if (this._additionsTail !== null) { 84159 this._additionsTail._nextAdded = null; 84160 } 84161 84162 if (this._movesTail !== null) { 84163 this._movesTail._nextMoved = null; 84164 } 84165 84166 if (this._itTail !== null) { 84167 this._itTail._next = null; 84168 } 84169 84170 if (this._removalsTail !== null) { 84171 this._removalsTail._nextRemoved = null; 84172 } 84173 84174 if (this._identityChangesTail !== null) { 84175 this._identityChangesTail._nextIdentityChange = null; 84176 } 84177 } 84178 /** @internal */ 84179 84180 84181 _reinsertAfter(record, prevRecord, index) { 84182 if (this._unlinkedRecords !== null) { 84183 this._unlinkedRecords.remove(record); 84184 } 84185 84186 const prev = record._prevRemoved; 84187 const next = record._nextRemoved; 84188 84189 if (prev === null) { 84190 this._removalsHead = next; 84191 } else { 84192 prev._nextRemoved = next; 84193 } 84194 84195 if (next === null) { 84196 this._removalsTail = prev; 84197 } else { 84198 next._prevRemoved = prev; 84199 } 84200 84201 this._insertAfter(record, prevRecord, index); 84202 84203 this._addToMoves(record, index); 84204 84205 return record; 84206 } 84207 /** @internal */ 84208 84209 84210 _moveAfter(record, prevRecord, index) { 84211 this._unlink(record); 84212 84213 this._insertAfter(record, prevRecord, index); 84214 84215 this._addToMoves(record, index); 84216 84217 return record; 84218 } 84219 /** @internal */ 84220 84221 84222 _addAfter(record, prevRecord, index) { 84223 this._insertAfter(record, prevRecord, index); 84224 84225 if (this._additionsTail === null) { 84226 // TODO(vicb): 84227 // assert(this._additionsHead === null); 84228 this._additionsTail = this._additionsHead = record; 84229 } else { 84230 // TODO(vicb): 84231 // assert(_additionsTail._nextAdded === null); 84232 // assert(record._nextAdded === null); 84233 this._additionsTail = this._additionsTail._nextAdded = record; 84234 } 84235 84236 return record; 84237 } 84238 /** @internal */ 84239 84240 84241 _insertAfter(record, prevRecord, index) { 84242 // TODO(vicb): 84243 // assert(record != prevRecord); 84244 // assert(record._next === null); 84245 // assert(record._prev === null); 84246 const next = prevRecord === null ? this._itHead : prevRecord._next; // TODO(vicb): 84247 // assert(next != record); 84248 // assert(prevRecord != record); 84249 84250 record._next = next; 84251 record._prev = prevRecord; 84252 84253 if (next === null) { 84254 this._itTail = record; 84255 } else { 84256 next._prev = record; 84257 } 84258 84259 if (prevRecord === null) { 84260 this._itHead = record; 84261 } else { 84262 prevRecord._next = record; 84263 } 84264 84265 if (this._linkedRecords === null) { 84266 this._linkedRecords = new _DuplicateMap(); 84267 } 84268 84269 this._linkedRecords.put(record); 84270 84271 record.currentIndex = index; 84272 return record; 84273 } 84274 /** @internal */ 84275 84276 84277 _remove(record) { 84278 return this._addToRemovals(this._unlink(record)); 84279 } 84280 /** @internal */ 84281 84282 84283 _unlink(record) { 84284 if (this._linkedRecords !== null) { 84285 this._linkedRecords.remove(record); 84286 } 84287 84288 const prev = record._prev; 84289 const next = record._next; // TODO(vicb):
vendor: 12,452 bytes, lines 84290-84810
84290 // assert((record._prev = null) === null); 84291 // assert((record._next = null) === null); 84292 84293 if (prev === null) { 84294 this._itHead = next; 84295 } else { 84296 prev._next = next; 84297 } 84298 84299 if (next === null) { 84300 this._itTail = prev; 84301 } else { 84302 next._prev = prev; 84303 } 84304 84305 return record; 84306 } 84307 /** @internal */ 84308 84309 84310 _addToMoves(record, toIndex) { 84311 // TODO(vicb): 84312 // assert(record._nextMoved === null); 84313 if (record.previousIndex === toIndex) { 84314 return record; 84315 } 84316 84317 if (this._movesTail === null) { 84318 // TODO(vicb): 84319 // assert(_movesHead === null); 84320 this._movesTail = this._movesHead = record; 84321 } else { 84322 // TODO(vicb): 84323 // assert(_movesTail._nextMoved === null); 84324 this._movesTail = this._movesTail._nextMoved = record; 84325 } 84326 84327 return record; 84328 } 84329 84330 _addToRemovals(record) { 84331 if (this._unlinkedRecords === null) { 84332 this._unlinkedRecords = new _DuplicateMap(); 84333 } 84334 84335 this._unlinkedRecords.put(record); 84336 84337 record.currentIndex = null; 84338 record._nextRemoved = null; 84339 84340 if (this._removalsTail === null) { 84341 // TODO(vicb): 84342 // assert(_removalsHead === null); 84343 this._removalsTail = this._removalsHead = record; 84344 record._prevRemoved = null; 84345 } else { 84346 // TODO(vicb): 84347 // assert(_removalsTail._nextRemoved === null); 84348 // assert(record._nextRemoved === null); 84349 record._prevRemoved = this._removalsTail; 84350 this._removalsTail = this._removalsTail._nextRemoved = record; 84351 } 84352 84353 return record; 84354 } 84355 /** @internal */ 84356 84357 84358 _addIdentityChange(record, item) { 84359 record.item = item; 84360 84361 if (this._identityChangesTail === null) { 84362 this._identityChangesTail = this._identityChangesHead = record; 84363 } else { 84364 this._identityChangesTail = this._identityChangesTail._nextIdentityChange = record; 84365 } 84366 84367 return record; 84368 } 84369 84370} 84371 84372class IterableChangeRecord_ { 84373 constructor(item, trackById) { 84374 this.item = item; 84375 this.trackById = trackById; 84376 this.currentIndex = null; 84377 this.previousIndex = null; 84378 /** @internal */ 84379 84380 this._nextPrevious = null; 84381 /** @internal */ 84382 84383 this._prev = null; 84384 /** @internal */ 84385 84386 this._next = null; 84387 /** @internal */ 84388 84389 this._prevDup = null; 84390 /** @internal */ 84391 84392 this._nextDup = null; 84393 /** @internal */ 84394 84395 this._prevRemoved = null; 84396 /** @internal */ 84397 84398 this._nextRemoved = null; 84399 /** @internal */ 84400 84401 this._nextAdded = null; 84402 /** @internal */ 84403 84404 this._nextMoved = null; 84405 /** @internal */ 84406 84407 this._nextIdentityChange = null; 84408 } 84409 84410} // A linked list of IterableChangeRecords with the same IterableChangeRecord_.item 84411 84412 84413class _DuplicateItemRecordList { 84414 constructor() { 84415 /** @internal */ 84416 this._head = null; 84417 /** @internal */ 84418 84419 this._tail = null; 84420 } 84421 /** 84422 * Append the record to the list of duplicates. 84423 * 84424 * Note: by design all records in the list of duplicates hold the same value in record.item. 84425 */ 84426 84427 84428 add(record) { 84429 if (this._head === null) { 84430 this._head = this._tail = record; 84431 record._nextDup = null; 84432 record._prevDup = null; 84433 } else { 84434 // TODO(vicb): 84435 // assert(record.item == _head.item || 84436 // record.item is num && record.item.isNaN && _head.item is num && _head.item.isNaN); 84437 this._tail._nextDup = record; 84438 record._prevDup = this._tail; 84439 record._nextDup = null; 84440 this._tail = record; 84441 } 84442 } // Returns a IterableChangeRecord_ having IterableChangeRecord_.trackById == trackById and 84443 // IterableChangeRecord_.currentIndex >= atOrAfterIndex 84444 84445 84446 get(trackById, atOrAfterIndex) { 84447 let record; 84448 84449 for (record = this._head; record !== null; record = record._nextDup) { 84450 if ((atOrAfterIndex === null || atOrAfterIndex <= record.currentIndex) && Object.is(record.trackById, trackById)) { 84451 return record; 84452 } 84453 } 84454 84455 return null; 84456 } 84457 /** 84458 * Remove one {@link IterableChangeRecord_} from the list of duplicates. 84459 * 84460 * Returns whether the list of duplicates is empty. 84461 */ 84462 84463 84464 remove(record) { 84465 // TODO(vicb): 84466 // assert(() { 84467 // // verify that the record being removed is in the list. 84468 // for (IterableChangeRecord_ cursor = _head; cursor != null; cursor = cursor._nextDup) { 84469 // if (identical(cursor, record)) return true; 84470 // } 84471 // return false; 84472 //}); 84473 const prev = record._prevDup; 84474 const next = record._nextDup; 84475 84476 if (prev === null) { 84477 this._head = next; 84478 } else { 84479 prev._nextDup = next; 84480 } 84481 84482 if (next === null) { 84483 this._tail = prev; 84484 } else { 84485 next._prevDup = prev; 84486 } 84487 84488 return this._head === null; 84489 } 84490 84491} 84492 84493class _DuplicateMap { 84494 constructor() { 84495 this.map = new Map(); 84496 } 84497 84498 put(record) { 84499 const key = record.trackById; 84500 let duplicates = this.map.get(key); 84501 84502 if (!duplicates) { 84503 duplicates = new _DuplicateItemRecordList(); 84504 this.map.set(key, duplicates); 84505 } 84506 84507 duplicates.add(record); 84508 } 84509 /** 84510 * Retrieve the `value` using key. Because the IterableChangeRecord_ value may be one which we 84511 * have already iterated over, we use the `atOrAfterIndex` to pretend it is not there. 84512 * 84513 * Use case: `[a, b, c, a, a]` if we are at index `3` which is the second `a` then asking if we 84514 * have any more `a`s needs to return the second `a`. 84515 */ 84516 84517 84518 get(trackById, atOrAfterIndex) { 84519 const key = trackById; 84520 const recordList = this.map.get(key); 84521 return recordList ? recordList.get(trackById, atOrAfterIndex) : null; 84522 } 84523 /** 84524 * Removes a {@link IterableChangeRecord_} from the list of duplicates. 84525 * 84526 * The list of duplicates also is removed from the map if it gets empty. 84527 */ 84528 84529 84530 remove(record) { 84531 const key = record.trackById; 84532 const recordList = this.map.get(key); // Remove the list of duplicates when it gets empty 84533 84534 if (recordList.remove(record)) { 84535 this.map.delete(key); 84536 } 84537 84538 return record; 84539 } 84540 84541 get isEmpty() { 84542 return this.map.size === 0; 84543 } 84544 84545 clear() { 84546 this.map.clear(); 84547 } 84548 84549} 84550 84551function getPreviousIndex(item, addRemoveOffset, moveOffsets) { 84552 const previousIndex = item.previousIndex; 84553 if (previousIndex === null) return previousIndex; 84554 let moveOffset = 0; 84555 84556 if (moveOffsets && previousIndex < moveOffsets.length) { 84557 moveOffset = moveOffsets[previousIndex]; 84558 } 84559 84560 return previousIndex + addRemoveOffset + moveOffset; 84561} 84562/** 84563 * @license 84564 * Copyright Google LLC All Rights Reserved. 84565 * 84566 * Use of this source code is governed by an MIT-style license that can be 84567 * found in the LICENSE file at https://angular.io/license 84568 */ 84569 84570 84571class DefaultKeyValueDifferFactory { 84572 constructor() {} 84573 84574 supports(obj) { 84575 return obj instanceof Map || isJsObject(obj); 84576 } 84577 84578 create() { 84579 return new DefaultKeyValueDiffer(); 84580 } 84581 84582} 84583 84584class DefaultKeyValueDiffer { 84585 constructor() { 84586 this._records = new Map(); 84587 this._mapHead = null; // _appendAfter is used in the check loop 84588 84589 this._appendAfter = null; 84590 this._previousMapHead = null; 84591 this._changesHead = null; 84592 this._changesTail = null; 84593 this._additionsHead = null; 84594 this._additionsTail = null; 84595 this._removalsHead = null; 84596 this._removalsTail = null; 84597 } 84598 84599 get isDirty() { 84600 return this._additionsHead !== null || this._changesHead !== null || this._removalsHead !== null; 84601 } 84602 84603 forEachItem(fn) { 84604 let record; 84605 84606 for (record = this._mapHead; record !== null; record = record._next) { 84607 fn(record); 84608 } 84609 } 84610 84611 forEachPreviousItem(fn) { 84612 let record; 84613 84614 for (record = this._previousMapHead; record !== null; record = record._nextPrevious) { 84615 fn(record); 84616 } 84617 } 84618 84619 forEachChangedItem(fn) { 84620 let record; 84621 84622 for (record = this._changesHead; record !== null; record = record._nextChanged) { 84623 fn(record); 84624 } 84625 } 84626 84627 forEachAddedItem(fn) { 84628 let record; 84629 84630 for (record = this._additionsHead; record !== null; record = record._nextAdded) { 84631 fn(record); 84632 } 84633 } 84634 84635 forEachRemovedItem(fn) { 84636 let record; 84637 84638 for (record = this._removalsHead; record !== null; record = record._nextRemoved) { 84639 fn(record); 84640 } 84641 } 84642 84643 diff(map) { 84644 if (!map) { 84645 map = new Map(); 84646 } else if (!(map instanceof Map || isJsObject(map))) { 84647 throw new RuntimeError(900 84648 /* RuntimeErrorCode.INVALID_DIFFER_INPUT */ 84649 , ngDevMode && `Error trying to diff '${stringify(map)}'. Only maps and objects are allowed`); 84650 } 84651 84652 return this.check(map) ? this : null; 84653 } 84654 84655 onDestroy() {} 84656 /** 84657 * Check the current state of the map vs the previous. 84658 * The algorithm is optimised for when the keys do no change. 84659 */ 84660 84661 84662 check(map) { 84663 this._reset(); 84664 84665 let insertBefore = this._mapHead; 84666 this._appendAfter = null; 84667 84668 this._forEach(map, (value, key) => { 84669 if (insertBefore && insertBefore.key === key) { 84670 this._maybeAddToChanges(insertBefore, value); 84671 84672 this._appendAfter = insertBefore; 84673 insertBefore = insertBefore._next; 84674 } else { 84675 const record = this._getOrCreateRecordForKey(key, value); 84676 84677 insertBefore = this._insertBeforeOrAppend(insertBefore, record); 84678 } 84679 }); // Items remaining at the end of the list have been deleted 84680 84681 84682 if (insertBefore) { 84683 if (insertBefore._prev) { 84684 insertBefore._prev._next = null; 84685 } 84686 84687 this._removalsHead = insertBefore; 84688 84689 for (let record = insertBefore; record !== null; record = record._nextRemoved) { 84690 if (record === this._mapHead) { 84691 this._mapHead = null; 84692 } 84693 84694 this._records.delete(record.key); 84695 84696 record._nextRemoved = record._next; 84697 record.previousValue = record.currentValue; 84698 record.currentValue = null; 84699 record._prev = null; 84700 record._next = null; 84701 } 84702 } // Make sure tails have no next records from previous runs 84703 84704 84705 if (this._changesTail) this._changesTail._nextChanged = null; 84706 if (this._additionsTail) this._additionsTail._nextAdded = null; 84707 return this.isDirty; 84708 } 84709 /** 84710 * Inserts a record before `before` or append at the end of the list when `before` is null. 84711 * 84712 * Notes: 84713 * - This method appends at `this._appendAfter`, 84714 * - This method updates `this._appendAfter`, 84715 * - The return value is the new value for the insertion pointer. 84716 */ 84717 84718 84719 _insertBeforeOrAppend(before, record) { 84720 if (before) { 84721 const prev = before._prev; 84722 record._next = before; 84723 record._prev = prev; 84724 before._prev = record; 84725 84726 if (prev) { 84727 prev._next = record; 84728 } 84729 84730 if (before === this._mapHead) { 84731 this._mapHead = record; 84732 } 84733 84734 this._appendAfter = before; 84735 return before; 84736 } 84737 84738 if (this._appendAfter) { 84739 this._appendAfter._next = record; 84740 record._prev = this._appendAfter; 84741 } else { 84742 this._mapHead = record; 84743 } 84744 84745 this._appendAfter = record; 84746 return null; 84747 } 84748 84749 _getOrCreateRecordForKey(key, value) { 84750 if (this._records.has(key)) { 84751 const record = this._records.get(key); 84752 84753 this._maybeAddToChanges(record, value); 84754 84755 const prev = record._prev; 84756 const next = record._next; 84757 84758 if (prev) { 84759 prev._next = next; 84760 } 84761 84762 if (next) { 84763 next._prev = prev; 84764 } 84765 84766 record._next = null; 84767 record._prev = null; 84768 return record; 84769 } 84770 84771 const record = new KeyValueChangeRecord_(key); 84772 84773 this._records.set(key, record); 84774 84775 record.currentValue = value; 84776 84777 this._addToAdditions(record); 84778 84779 return record; 84780 } 84781 /** @internal */ 84782 84783 84784 _reset() { 84785 if (this.isDirty) { 84786 let record; // let `_previousMapHead` contain the state of the map before the changes 84787 84788 this._previousMapHead = this._mapHead; 84789 84790 for (record = this._previousMapHead; record !== null; record = record._next) { 84791 record._nextPrevious = record._next; 84792 } // Update `record.previousValue` with the value of the item before the changes 84793 // We need to update all changed items (that's those which have been added and changed) 84794 84795 84796 for (record = this._changesHead; record !== null; record = record._nextChanged) { 84797 record.previousValue = record.currentValue; 84798 } 84799 84800 for (record = this._additionsHead; record != null; record = record._nextAdded) { 84801 record.previousValue = record.currentValue; 84802 } 84803 84804 this._changesHead = this._changesTail = null; 84805 this._additionsHead = this._additionsTail = null; 84806 this._removalsHead = null; 84807 } 84808 } // Add the record or a given key to the list of changes only when the value has actually changed 84809 84810
84811 _maybeAddToChanges(record, newValue) { 84812 if (!Object.is(newValue, record.currentValue)) { 84813 record.previousValue = record.currentValue; 84814 record.currentValue = newValue; 84815 84816 this._addToChanges(record); 84817 } 84818 } 84819 84820 _addToAdditions(record) { 84821 if (this._additionsHead === null) { 84822 this._additionsHead = this._additionsTail = record; 84823 } else { 84824 this._additionsTail._nextAdded = record; 84825 this._additionsTail = record; 84826 } 84827 } 84828 84829 _addToChanges(record) { 84830 if (this._changesHead === null) { 84831 this._changesHead = this._changesTail = record; 84832 } else { 84833 this._changesTail._nextChanged = record; 84834 this._changesTail = record; 84835 } 84836 } 84837 /** @internal */ 84838 84839 84840 _forEach(obj, fn) { 84841 if (obj instanceof Map) { 84842 obj.forEach(fn); 84843 } else { 84844 Object.keys(obj).forEach(k => fn(obj[k], k)); 84845 } 84846 } 84847 84848} 84849 84850class KeyValueChangeRecord_ { 84851 constructor(key) { 84852 this.key = key; 84853 this.previousValue = null; 84854 this.currentValue = null; 84855 /** @internal */ 84856 84857 this._nextPrevious = null; 84858 /** @internal */ 84859 84860 this._next = null; 84861 /** @internal */ 84862 84863 this._prev = null; 84864 /** @internal */ 84865 84866 this._nextAdded = null; 84867 /** @internal */ 84868 84869 this._nextRemoved = null; 84870 /** @internal */ 84871 84872 this._nextChanged = null; 84873 } 84874 84875} 84876/** 84877 * @license 84878 * Copyright Google LLC All Rights Reserved. 84879 * 84880 * Use of this source code is governed by an MIT-style license that can be 84881 * found in the LICENSE file at https://angular.io/license 84882 */ 84883 84884 84885function defaultIterableDiffersFactory() { 84886 return new IterableDiffers([new DefaultIterableDifferFactory()]); 84887} 84888/** 84889 * A repository of different iterable diffing strategies used by NgFor, NgClass, and others. 84890 * 84891 * @publicApi 84892 */ 84893 84894 84895class IterableDiffers { 84896 constructor(factories) { 84897 this.factories = factories; 84898 } 84899 84900 static create(factories, parent) { 84901 if (parent != null) { 84902 const copied = parent.factories.slice(); 84903 factories = factories.concat(copied); 84904 } 84905 84906 return new IterableDiffers(factories); 84907 } 84908 /** 84909 * Takes an array of {@link IterableDifferFactory} and returns a provider used to extend the 84910 * inherited {@link IterableDiffers} instance with the provided factories and return a new 84911 * {@link IterableDiffers} instance. 84912 * 84913 * @usageNotes 84914 * ### Example 84915 * 84916 * The following example shows how to extend an existing list of factories, 84917 * which will only be applied to the injector for this component and its children. 84918 * This step is all that's required to make a new {@link IterableDiffer} available. 84919 * 84920 * ``` 84921 * @Component({ 84922 * viewProviders: [ 84923 * IterableDiffers.extend([new ImmutableListDiffer()]) 84924 * ] 84925 * }) 84926 * ``` 84927 */ 84928 84929 84930 static extend(factories) { 84931 return { 84932 provide: IterableDiffers, 84933 useFactory: parent => { 84934 // if parent is null, it means that we are in the root injector and we have just overridden 84935 // the default injection mechanism for IterableDiffers, in such a case just assume 84936 // `defaultIterableDiffersFactory`. 84937 return IterableDiffers.create(factories, parent || defaultIterableDiffersFactory()); 84938 }, 84939 // Dependency technically isn't optional, but we can provide a better error message this way. 84940 deps: [[IterableDiffers, new SkipSelf(), new Optional()]] 84941 }; 84942 } 84943 84944 find(iterable) { 84945 const factory = this.factories.find(f => f.supports(iterable)); 84946 84947 if (factory != null) { 84948 return factory; 84949 } else { 84950 throw new RuntimeError(901 84951 /* RuntimeErrorCode.NO_SUPPORTING_DIFFER_FACTORY */ 84952 , ngDevMode && `Cannot find a differ supporting object '${iterable}' of type '${getTypeNameForDebugging(iterable)}'`); 84953 } 84954 } 84955 84956} 84957/** @nocollapse */ 84958 84959 84960IterableDiffers.ɵprov = ɵɵdefineInjectable({ 84961 token: IterableDiffers, 84962 providedIn: 'root', 84963 factory: defaultIterableDiffersFactory 84964}); 84965 84966function getTypeNameForDebugging(type) { 84967 return type['name'] || typeof type; 84968} 84969/** 84970 * @license 84971 * Copyright Google LLC All Rights Reserved. 84972 * 84973 * Use of this source code is governed by an MIT-style license that can be 84974 * found in the LICENSE file at https://angular.io/license 84975 */ 84976 84977 84978function defaultKeyValueDiffersFactory() { 84979 return new KeyValueDiffers([new DefaultKeyValueDifferFactory()]); 84980} 84981/** 84982 * A repository of different Map diffing strategies used by NgClass, NgStyle, and others. 84983 * 84984 * @publicApi 84985 */ 84986 84987 84988class KeyValueDiffers { 84989 constructor(factories) { 84990 this.factories = factories; 84991 } 84992 84993 static create(factories, parent) { 84994 if (parent) { 84995 const copied = parent.factories.slice(); 84996 factories = factories.concat(copied); 84997 } 84998 84999 return new KeyValueDiffers(factories); 85000 } 85001 /** 85002 * Takes an array of {@link KeyValueDifferFactory} and returns a provider used to extend the 85003 * inherited {@link KeyValueDiffers} instance with the provided factories and return a new 85004 * {@link KeyValueDiffers} instance. 85005 * 85006 * @usageNotes 85007 * ### Example 85008 * 85009 * The following example shows how to extend an existing list of factories, 85010 * which will only be applied to the injector for this component and its children. 85011 * This step is all that's required to make a new {@link KeyValueDiffer} available. 85012 * 85013 * ``` 85014 * @Component({ 85015 * viewProviders: [ 85016 * KeyValueDiffers.extend([new ImmutableMapDiffer()]) 85017 * ] 85018 * }) 85019 * ``` 85020 */ 85021 85022 85023 static extend(factories) { 85024 return { 85025 provide: KeyValueDiffers, 85026 useFactory: parent => { 85027 // if parent is null, it means that we are in the root injector and we have just overridden 85028 // the default injection mechanism for KeyValueDiffers, in such a case just assume 85029 // `defaultKeyValueDiffersFactory`. 85030 return KeyValueDiffers.create(factories, parent || defaultKeyValueDiffersFactory()); 85031 }, 85032 // Dependency technically isn't optional, but we can provide a better error message this way. 85033 deps: [[KeyValueDiffers, new SkipSelf(), new Optional()]] 85034 }; 85035 } 85036 85037 find(kv) { 85038 const factory = this.factories.find(f => f.supports(kv)); 85039 85040 if (factory) { 85041 return factory; 85042 } 85043 85044 throw new RuntimeError(901 85045 /* RuntimeErrorCode.NO_SUPPORTING_DIFFER_FACTORY */ 85046 , ngDevMode && `Cannot find a differ supporting object '${kv}'`); 85047 } 85048 85049} 85050/** @nocollapse */ 85051 85052 85053KeyValueDiffers.ɵprov = ɵɵdefineInjectable({ 85054 token: KeyValueDiffers, 85055 providedIn: 'root', 85056 factory: defaultKeyValueDiffersFactory 85057}); 85058/** 85059 * @license 85060 * Copyright Google LLC All Rights Reserved. 85061 * 85062 * Use of this source code is governed by an MIT-style license that can be 85063 * found in the LICENSE file at https://angular.io/license 85064 */ 85065 85066/** 85067 * Structural diffing for `Object`s and `Map`s. 85068 */ 85069 85070const keyValDiff = [new DefaultKeyValueDifferFactory()]; 85071/** 85072 * Structural diffing for `Iterable` types such as `Array`s. 85073 */ 85074 85075const iterableDiff = [new DefaultIterableDifferFactory()]; 85076const defaultIterableDiffers = new IterableDiffers(iterableDiff); 85077const defaultKeyValueDiffers = new KeyValueDiffers(keyValDiff); 85078/** 85079 * @license 85080 * Copyright Google LLC All Rights Reserved. 85081 * 85082 * Use of this source code is governed by an MIT-style license that can be 85083 * found in the LICENSE file at https://angular.io/license 85084 */ 85085 85086/** 85087 * @license 85088 * Copyright Google LLC All Rights Reserved. 85089 * 85090 * Use of this source code is governed by an MIT-style license that can be 85091 * found in the LICENSE file at https://angular.io/license 85092 */ 85093 85094/** 85095 * This platform has to be included in any other platform 85096 * 85097 * @publicApi 85098 */ 85099 85100const platformCore = createPlatformFactory(null, 'core', []); 85101/** 85102 * @license 85103 * Copyright Google LLC All Rights Reserved. 85104 * 85105 * Use of this source code is governed by an MIT-style license that can be 85106 * found in the LICENSE file at https://angular.io/license 85107 */ 85108 85109/** 85110 * Re-exported by `BrowserModule`, which is included automatically in the root 85111 * `AppModule` when you create a new app with the CLI `new` command. Eagerly injects 85112 * `ApplicationRef` to instantiate it. 85113 * 85114 * @publicApi 85115 */ 85116 85117class ApplicationModule { 85118 // Inject ApplicationRef to make it eager... 85119 constructor(appRef) {} 85120 85121} 85122 85123ApplicationModule.ɵfac = function ApplicationModule_Factory(t) { 85124 return new (t || ApplicationModule)(ɵɵinject(ApplicationRef)); 85125}; 85126 85127ApplicationModule.ɵmod = /*@__PURE__*/ɵɵdefineNgModule({ 85128 type: ApplicationModule 85129}); 85130ApplicationModule.ɵinj = /*@__PURE__*/ɵɵdefineInjector({}); 85131 85132(function () { 85133 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationModule, [{ 85134 type: NgModule 85135 }], function () { 85136 return [{ 85137 type: ApplicationRef 85138 }]; 85139 }, null); 85140})(); 85141/** 85142 * @license 85143 * Copyright Google LLC All Rights Reserved. 85144 * 85145 * Use of this source code is governed by an MIT-style license that can be 85146 * found in the LICENSE file at https://angular.io/license 85147 */ 85148 85149/** Coerces a value (typically a string) to a boolean. */ 85150 85151 85152function coerceToBoolean(value) { 85153 return typeof value === 'boolean' ? value : value != null && value !== 'false'; 85154} 85155/** 85156 * @license 85157 * Copyright Google LLC All Rights Reserved. 85158 * 85159 * Use of this source code is governed by an MIT-style license that can be 85160 * found in the LICENSE file at https://angular.io/license 85161 */ 85162// TODO(alxhub): allows tests to compile, can be removed when tests have been updated. 85163 85164 85165const ɵivyEnabled = true; 85166/** 85167 * @license 85168 * Copyright Google LLC All Rights Reserved. 85169 * 85170 * Use of this source code is governed by an MIT-style license that can be 85171 * found in the LICENSE file at https://angular.io/license 85172 */ 85173 85174/** 85175 * Compiles a partial directive declaration object into a full directive definition object. 85176 * 85177 * @codeGenApi 85178 */ 85179 85180function ɵɵngDeclareDirective(decl) { 85181 const compiler = getCompilerFacade({ 85182 usage: 1 85183 /* JitCompilerUsage.PartialDeclaration */ 85184 , 85185 kind: 'directive', 85186 type: decl.type 85187 }); 85188 return compiler.compileDirectiveDeclaration(angularCoreEnv, `ng:///${decl.type.n
85188ame}/ɵfac.js`, decl); 85189} 85190/** 85191 * Evaluates the class metadata declaration. 85192 * 85193 * @codeGenApi 85194 */ 85195 85196 85197function ɵɵngDeclareClassMetadata(decl) { 85198 setClassMetadata(decl.type, decl.decorators, decl.ctorParameters ?? null, decl.propDecorators ?? null); 85199} 85200/** 85201 * Compiles a partial component declaration object into a full component definition object. 85202 * 85203 * @codeGenApi 85204 */ 85205 85206 85207function ɵɵngDeclareComponent(decl) { 85208 const compiler = getCompilerFacade({ 85209 usage: 1 85210 /* JitCompilerUsage.PartialDeclaration */ 85211 , 85212 kind: 'component', 85213 type: decl.type 85214 }); 85215 return compiler.compileComponentDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵcmp.js`, decl); 85216} 85217/** 85218 * Compiles a partial pipe declaration object into a full pipe definition object. 85219 * 85220 * @codeGenApi 85221 */ 85222 85223 85224function ɵɵngDeclareFactory(decl) { 85225 const compiler = getCompilerFacade({ 85226 usage: 1 85227 /* JitCompilerUsage.PartialDeclaration */ 85228 , 85229 kind: getFactoryKind(decl.target), 85230 type: decl.type 85231 }); 85232 return compiler.compileFactoryDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl); 85233} 85234 85235function getFactoryKind(target) { 85236 switch (target) { 85237 case FactoryTarget.Directive: 85238 return 'directive'; 85239 85240 case FactoryTarget.Component: 85241 return 'component'; 85242 85243 case FactoryTarget.Injectable: 85244 return 'injectable'; 85245 85246 case FactoryTarget.Pipe: 85247 return 'pipe'; 85248 85249 case FactoryTarget.NgModule: 85250 return 'NgModule'; 85251 } 85252} 85253/** 85254 * Compiles a partial injectable declaration object into a full injectable definition object. 85255 * 85256 * @codeGenApi 85257 */ 85258 85259 85260function ɵɵngDeclareInjectable(decl) { 85261 const compiler = getCompilerFacade({ 85262 usage: 1 85263 /* JitCompilerUsage.PartialDeclaration */ 85264 , 85265 kind: 'injectable', 85266 type: decl.type 85267 }); 85268 return compiler.compileInjectableDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵprov.js`, decl); 85269} 85270/** 85271 * Compiles a partial injector declaration object into a full injector definition object. 85272 * 85273 * @codeGenApi 85274 */ 85275 85276 85277function ɵɵngDeclareInjector(decl) { 85278 const compiler = getCompilerFacade({ 85279 usage: 1 85280 /* JitCompilerUsage.PartialDeclaration */ 85281 , 85282 kind: 'NgModule', 85283 type: decl.type 85284 }); 85285 return compiler.compileInjectorDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵinj.js`, decl); 85286} 85287/** 85288 * Compiles a partial NgModule declaration object into a full NgModule definition object. 85289 * 85290 * @codeGenApi 85291 */ 85292 85293 85294function ɵɵngDeclareNgModule(decl) { 85295 const compiler = getCompilerFacade({ 85296 usage: 1 85297 /* JitCompilerUsage.PartialDeclaration */ 85298 , 85299 kind: 'NgModule', 85300 type: decl.type 85301 }); 85302 return compiler.compileNgModuleDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵmod.js`, decl); 85303} 85304/** 85305 * Compiles a partial pipe declaration object into a full pipe definition object. 85306 * 85307 * @codeGenApi 85308 */ 85309 85310 85311function ɵɵngDeclarePipe(decl) { 85312 const compiler = getCompilerFacade({ 85313 usage: 1 85314 /* JitCompilerUsage.PartialDeclaration */ 85315 , 85316 kind: 'pipe', 85317 type: decl.type 85318 }); 85319 return compiler.compilePipeDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵpipe.js`, decl); 85320} 85321/** 85322 * @license 85323 * Copyright Google LLC All Rights Reserved. 85324 * 85325 * Use of this source code is governed by an MIT-style license that can be 85326 * found in the LICENSE file at https://angular.io/license 85327 */ 85328// clang-format on 85329 85330/** 85331 * @license 85332 * Copyright Google LLC All Rights Reserved. 85333 * 85334 * Use of this source code is governed by an MIT-style license that can be 85335 * found in the LICENSE file at https://angular.io/license 85336 */ 85337 85338/** 85339 * Creates a `ComponentRef` instance based on provided component type and a set of options. 85340 * 85341 * @usageNotes 85342 * 85343 * The example below demonstrates how the `createComponent` function can be used 85344 * to create an instance of a ComponentRef dynamically and attach it to an ApplicationRef, 85345 * so that it gets included into change detection cycles. 85346 * 85347 * Note: the example uses standalone components, but the function can also be used for 85348 * non-standalone components (declared in an NgModule) as well. 85349 * 85350 * ```typescript 85351 * @Component({ 85352 * standalone: true, 85353 * template: `Hello {{ name }}!` 85354 * }) 85355 * class HelloComponent { 85356 * name = 'Angular'; 85357 * } 85358 * 85359 * @Component({ 85360 * standalone: true, 85361 * template: `<div id="hello-component-host"></div>` 85362 * }) 85363 * class RootComponent {} 85364 * 85365 * // Bootstrap an application. 85366 * const applicationRef = await bootstrapApplication(RootComponent); 85367 *
85368 * // Locate a DOM node that would be used as a host. 85369 * const host = document.getElementById('hello-component-host'); 85370 * 85371 * // Get an `EnvironmentInjector` instance from the `ApplicationRef`. 85372 * const environmentInjector = applicationRef.injector; 85373 * 85374 * // We can now create a `ComponentRef` instance. 85375 * const componentRef = createComponent(HelloComponent, {host, environmentInjector}); 85376 * 85377 * // Last step is to register the newly created ref using the `ApplicationRef` instance 85378 * // to include the component view into change detection cycles. 85379 * applicationRef.attachView(componentRef.hostView); 85380 * ``` 85381 * 85382 * @param component Component class reference. 85383 * @param options Set of options to use: 85384 * * `environmentInjector`: An `EnvironmentInjector` instance to be used for the component, see 85385 * additional info about it at https://angular.io/guide/standalone-components#environment-injectors. 85386 * * `hostElement` (optional): A DOM node that should act as a host node for the component. If not 85387 * provided, Angular creates one based on the tag name used in the component selector (and falls 85388 * back to using `div` if selector doesn't have tag name info). 85389 * * `elementInjector` (optional): An `ElementInjector` instance, see additional info about it at 85390 * https://angular.io/guide/hierarchical-dependency-injection#elementinjector. 85391 * * `projectableNodes` (optional): A list of DOM nodes that should be projected through 85392 * [`<ng-content>`](api/core/ng-content) of the new component instance. 85393 * @returns ComponentRef instance that represents a given Component. 85394 * 85395 * @publicApi 85396 */ 85397 85398 85399function createComponent(component, options) { 85400 ngDevMode && assertComponentDef(component); 85401 const componentDef = getComponentDef(component); 85402 const elementInjector = options.elementInjector || getNullInjector(); 85403 const factory = new ComponentFactory(componentDef); 85404 return factory.create(elementInjector, options.projectableNodes, options.hostElement, options.environmentInjector); 85405} 85406/** 85407 * Creates an object that allows to retrieve component metadata. 85408 * 85409 * @usageNotes 85410 * 85411 * The example below demonstrates how to use the function and how the fields 85412 * of the returned object map to the component metadata. 85413 * 85414 * ```typescript 85415 * @Component({ 85416 * standalone: true, 85417 * selector: 'foo-component', 85418 * template: ` 85419 * <ng-content></ng-content> 85420 * <ng-content select="content-selector-a"></ng-content> 85421 * `, 85422 * }) 85423 * class FooComponent { 85424 * @Input('inputName') inputPropName: string; 85425 * @Output('outputName') outputPropName = new EventEmitter<void>(); 85426 * } 85427 * 85428 * const mirror = reflectComponentType(FooComponent); 85429 * expect(mirror.type).toBe(FooComponent); 85430 * expect(mirror.selector).toBe('foo-component'); 85431 * expect(mirror.isStandalone).toBe(true); 85432 * expect(mirror.inputs).toEqual([{propName: 'inputName', templateName: 'inputPropName'}]); 85433 * expect(mirror.outputs).toEqual([{propName: 'outputName', templateName: 'outputPropName'}]); 85434 * expect(mirror.ngContentSelectors).toEqual([ 85435 * '*', // first `<ng-content>` in a template, the selector defaults to `*` 85436 * 'content-selector-a' // second `<ng-content>` in a template 85437 * ]); 85438 * ``` 85439 * 85440 * @param component Component class reference. 85441 * @returns An object that allows to retrieve component metadata. 85442 * 85443 * @publicApi 85444 */ 85445 85446 85447function reflectComponentType(component) { 85448 const componentDef = getComponentDef(component); 85449 if (!componentDef) return null; 85450 const factory = new ComponentFactory(componentDef); 85451 return { 85452 get selector() { 85453 return factory.selector; 85454 }, 85455 85456 get type() { 85457 return factory.componentType; 85458 }, 85459 85460 get inputs() { 85461 return factory.inputs; 85462 }, 85463 85464 get outputs() { 85465 return factory.outputs; 85466 }, 85467 85468 get ngContentSelectors() { 85469 return factory.ngContentSelectors; 85470 }, 85471 85472 get isStandalone() { 85473 return componentDef.standalone; 85474 } 85475 85476 }; 85477} 85478/** 85479 * @license 85480 * Copyright Google LLC All Rights Reserved. 85481 * 85482 * Use of this source code is governed by an MIT-style license that can be 85483 * found in the LICENSE file at https://angular.io/license 85484 */ 85485 85486 85487if (typeof ngDevMode !== 'undefined' && ngDevMode) { 85488 // This helper is to give a reasonable error message to people upgrading to v9 that have not yet 85489 // installed `@angular/localize` in their app. 85490 // tslint:disable-next-line: no-toplevel-property-access 85491 _global.$localize = _global.$localize || function () { 85492 throw new Error('It looks like your application or one of its dependencies is using i18n.\n' + 'Angular 9 introduced a global `$localize()` function that needs to be loaded.\n' + 'Please run `ng add @angular/localize` from the Angular CLI.\n' + '(For non-CLI projects, add `import \'@angular/localize/init\';` to your `polyfills.ts` file.\n' + 'For server-side rendering applications add the import to your `main.server.ts` file.)'); 85493 }; 85494} 85495/** 85496 * @license 85497 * Copyright Google LLC All Rights Reserved. 85498 * 85499 * Use of this source code is governed by an MIT-style license that can be 85500 * found in the LICENSE file at https://angular.io/license 85501 */ 85502// This file only reexports content of the `src` folder. Keep it that way. 85503 85504/** 85505 * @license 85506 * Copyright Google LLC All Rights Reserved. 85507 * 85508 * Use of this source code is governed by an MIT-style license that can be 85509 * found in the LICENSE file at https://angular.io/license 85510 */ 85511 85512/** 85513 * Generated bundle index. Do not edit. 85514 */ 85515 85516 85517 85518 85519/***/ }), 85520 85521/***/ 2508: 85522/*!********************************************************!*\ 85523 !*** ./node_modules/@angular/forms/fesm2020/forms.mjs ***! 85524 \********************************************************/ 85525/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 85526 85527__webpack_require__.r(__webpack_exports__); 85528/* harmony export */ __webpack_require__.d(__webpack_exports__, { 85529/* harmony export */ "AbstractControl": () => (/* binding */ AbstractControl), 85530/* harmony export */ "AbstractControlDirective": () => (/* binding */ AbstractControlDirective), 85531/* harmony export */ "AbstractFormGroupDirective": () => (/* binding */ AbstractFormGroupDirective), 85532/* harmony export */ "COMPOSITION_BUFFER_MODE": () => (/* binding */ COMPOSITION_BUFFER_MODE), 85533/* harmony export */ "CheckboxControlValueAccessor": () => (/* binding */ CheckboxControlValueAccessor), 85534/* harmony export */ "CheckboxRequiredValidator": () => (/* binding */ CheckboxRequiredValidator), 85535/* harmony export */ "ControlContainer": () => (/* binding */ ControlContainer), 85536/* harmony export */ "DefaultValueAccessor": () => (/* binding */ DefaultValueAccessor), 85537/* harmony export */ "EmailValidator": () => (/* binding */ EmailValidator), 85538/* harmony export */ "FormArray": () => (/* binding */ FormArray), 85539/* harmony export */ "FormArrayName": () => (/* binding */ FormArrayName), 85540/* harmony export */ "FormBuilder": () => (/* binding */ FormBuilder), 85541/* harmony export */ "FormControl": () => (/* binding */ FormControl), 85542/* harmony export */ "FormControlDirective": () => (/* binding */ FormControlDirective), 85543/* harmony export */ "FormControlName": () => (/* binding */ FormControlName), 85544/* harmony export */ "FormGroup": () => (/* binding */ FormGroup), 85545/* harmony export */ "FormGroupDirective": () => (/* binding */ FormGroupDirective), 85546/* harmony export */ "FormGroupName": () => (/* binding */ FormGroupName), 85547/* harmony export */ "FormRecord": () => (/* binding */ FormRecord), 85548/* harmony export */ "FormsModule": () => (/* binding */ FormsModule), 85549/* harmony export */ "MaxLengthValidator": () => (/* binding */ MaxLengthValidator), 85550/* harmony export */ "MaxValidator": () => (/* binding */ MaxValidator), 85551/* harmony export */ "MinLengthValidator": () => (/* binding */ MinLengthValidator), 85552/* harmony export */ "MinValidator": () => (/* binding */ MinValidator), 85553/* harmony export */ "NG_ASYNC_VALIDATORS": () => (/* binding */ NG_ASYNC_VALIDATORS), 85554/* harmony export */ "NG_VALIDATORS": () => (/* binding */ NG_VALIDATORS), 85555/* harmony export */ "NG_VALUE_ACCESSOR": () => (/* binding */ NG_VALUE_ACCESSOR), 85556/* harmony export */ "NgControl": () => (/* binding */ NgControl), 85557/* harmony export */ "NgControlStatus": () => (/* binding */ NgControlStatus), 85558/* harmony export */ "NgControlStatusGroup": () => (/* binding */ NgControlStatusGroup), 85559/* harmony export */ "NgForm": () => (/* binding */ NgForm), 85560/* harmony export */ "NgModel": () => (/* binding */ NgModel), 85561/* harmony export */ "NgModelGroup": () => (/* binding */ NgModelGroup), 85562/* harmony export */ "NgSelectOption": () => (/* binding */ NgSelectOption), 85563/* harmony export */ "NonNullableFormBuilder": () => (/* binding */ NonNullableFormBuilder), 85564/* harmony export */ "NumberValueAccessor": () => (/* binding */ NumberValueAccessor), 85565/* harmony export */ "PatternValidator": () => (/* binding */ PatternValidator), 85566/* harmony export */ "RadioControlValueAccessor": () => (/* binding */ RadioControlValueAccessor), 85567/* harmony export */ "RangeValueAccessor": () => (/* binding */ RangeValueAccessor), 85568/* harmony export */ "ReactiveFormsModule": () => (/* binding */ ReactiveFormsModule), 85569/* harmony export */ "RequiredValidator": () => (/* binding */ RequiredValidator), 85570/* harmony export */ "SelectControlValueAccessor": () => (/* binding */ SelectControlValueAccessor), 85571/* harmony export */ "SelectMultipleControlValueAccessor": () => (/* binding */ SelectMultipleControlValueAccessor), 85572/* harmony export */ "UntypedFormArray": () => (/* binding */ UntypedFormArray), 85573/* harmony export */ "UntypedFormBuilder": () => (/* binding */ UntypedFormBuilder), 85574/* harmony export */ "UntypedFormControl": () => (/* binding */ UntypedFormControl), 85575/* harmony export */ "UntypedFormGroup": () => (/* binding */ UntypedFormGroup), 85576/* harmony export */ "VERSION": () => (/* binding */ VERSION), 85577/* harmony export */ "Validators": () => (/* binding */ Validators), 85578/* harmony export */ "ɵInternalFormsSharedModule": () => (/* binding */ ɵInternalFormsSharedModule), 85579/* harmony export */ "ɵNgNoValidate": () => (/* binding */ ɵNgNoValidate),
85580/* harmony export */ "ɵNgSelectMultipleOption": () => (/* binding */ ɵNgSelectMultipleOption) 85581/* harmony export */ }); 85582/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 2560); 85583/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common */ 4666); 85584/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 4383); 85585/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 4350); 85586/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs/operators */ 6942); 85587/** 85588 * @license Angular v14.2.10 85589 * (c) 2010-2022 Google LLC. https://angular.io/ 85590 * License: MIT 85591 */ 85592 85593 85594 85595 85596 85597/** 85598 * @license 85599 * Copyright Google LLC All Rights Reserved. 85600 * 85601 * Use of this source code is governed by an MIT-style license that can be 85602 * found in the LICENSE file at https://angular.io/license 85603 */ 85604 85605/** 85606 * Base class for all ControlValueAccessor classes defined in Forms package. 85607 * Contains common logic and utility functions. 85608 * 85609 * Note: this is an *internal-only* class and should not be extended or used directly in 85610 * applications code. 85611 */ 85612 85613class BaseControlValueAccessor { 85614 constructor(_renderer, _elementRef) { 85615 this._renderer = _renderer; 85616 this._elementRef = _elementRef; 85617 /** 85618 * The registered callback function called when a change or input event occurs on the input 85619 * element. 85620 * @nodoc 85621 */ 85622 85623 this.onChange = _ => {}; 85624 /** 85625 * The registered callback function called when a blur event occurs on the input element. 85626 * @nodoc 85627 */ 85628 85629 85630 this.onTouched = () => {}; 85631 } 85632 /** 85633 * Helper method that sets a property on a target element using the current Renderer 85634 * implementation. 85635 * @nodoc 85636 */ 85637 85638 85639 setProperty(key, value) { 85640 this._renderer.setProperty(this._elementRef.nativeElement, key, value); 85641 } 85642 /** 85643 * Registers a function called when the control is touched. 85644 * @nodoc 85645 */ 85646 85647 85648 registerOnTouched(fn) { 85649 this.onTouched = fn; 85650 } 85651 /** 85652 * Registers a function called when the control value changes. 85653 * @nodoc 85654 */ 85655 85656 85657 registerOnChange(fn) { 85658 this.onChange = fn; 85659 } 85660 /** 85661 * Sets the "disabled" property on the range input element. 85662 * @nodoc 85663 */ 85664 85665 85666 setDisabledState(isDisabled) { 85667 this.setProperty('disabled', isDisabled); 85668 } 85669 85670} 85671 85672BaseControlValueAccessor.ɵfac = function BaseControlValueAccessor_Factory(t) { 85673 return new (t || BaseControlValueAccessor)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef)); 85674}; 85675 85676BaseControlValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 85677 type: BaseControlValueAccessor 85678}); 85679 85680(function () { 85681 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](BaseControlValueAccessor, [{ 85682 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive 85683 }], function () { 85684 return [{ 85685 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2 85686 }, { 85687 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef 85688 }]; 85689 }, null); 85690})(); 85691/** 85692 * Base class for all built-in ControlValueAccessor classes (except DefaultValueAccessor, which is 85693 * used in case no other CVAs can be found). We use this class to distinguish between default CVA, 85694 * built-in CVAs and custom CVAs, so that Forms logic can recognize built-in CVAs and treat custom 85695 * ones with higher priority (when both built-in and custom CVAs are present). 85696 * 85697 * Note: this is an *internal-only* class and should not be extended or used directly in 85698 * applications code. 85699 */ 85700 85701 85702class BuiltInControlValueAccessor extends BaseControlValueAccessor {} 85703 85704BuiltInControlValueAccessor.ɵfac = /* @__PURE__ */function () { 85705 let ɵBuiltInControlValueAccessor_BaseFactory; 85706 return function BuiltInControlValueAccessor_Factory(t) { 85707 return (ɵBuiltInControlValueAccessor_BaseFactory || (ɵBuiltInControlValueAccessor_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](BuiltInControlValueAccessor)))(t || BuiltInControlValueAccessor); 85708 }; 85709}(); 85710 85711BuiltInControlValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 85712 type: BuiltInControlValueAccessor, 85713 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 85714}); 85715 85716(function () { 85717 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](BuiltInControlValueAccessor, [{ 85718 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive 85719 }], null, null); 85720})(); 85721/** 85722 * Used to provide a `ControlValueAccessor` for form controls. 85723 * 85724 * See `DefaultValueAccessor` for how to implement one. 85725 * 85726 * @publicApi 85727 */ 85728 85729 85730const NG_VALUE_ACCESSOR = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('NgValueAccessor'); 85731/** 85732 * @license 85733 * Copyright Google LLC All Rights Reserved. 85734 * 85735 * Use of this source code is governed by an MIT-style license that can be 85736 * found in the LICENSE file at https://angular.io/license 85737 */ 85738 85739const CHECKBOX_VALUE_ACCESSOR = { 85740 provide: NG_VALUE_ACCESSOR, 85741 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => CheckboxControlValueAccessor), 85742 multi: true 85743}; 85744/** 85745 * @description 85746 * A `ControlValueAccessor` for writing a value and listening to changes on a checkbox input 85747 * element. 85748 * 85749 * @usageNotes 85750 * 85751 * ### Using a checkbox with a reactive form. 85752 * 85753 * The following example shows how to use a checkbox with a reactive form. 85754 * 85755 * ```ts 85756 * const rememberLoginControl = new FormControl(); 85757 * ``` 85758 * 85759 * ``` 85760 * <input type="checkbox" [formControl]="rememberLoginControl"> 85761 * ``` 85762 * 85763 * @ngModule ReactiveFormsModule 85764 * @ngModule FormsModule 85765 * @publicApi 85766 */ 85767 85768class CheckboxControlValueAccessor extends BuiltInControlValueAccessor { 85769 /** 85770 * Sets the "checked" property on the input element. 85771 * @nodoc 85772 */ 85773 writeValue(value) { 85774 this.setProperty('checked', value); 85775 } 85776 85777} 85778 85779CheckboxControlValueAccessor.ɵfac = /* @__PURE__ */function () { 85780 let ɵCheckboxControlValueAccessor_BaseFactory; 85781 return function CheckboxControlValueAccessor_Factory(t) { 85782 return (ɵCheckboxControlValueAccessor_BaseFactory || (ɵCheckboxControlValueAccessor_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](CheckboxControlValueAccessor)))(t || CheckboxControlValueAccessor); 85783 }; 85784}(); 85785 85786CheckboxControlValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 85787 type: CheckboxControlValueAccessor, 85788 selectors: [["input", "type", "checkbox", "formControlName", ""], ["input", "type", "checkbox", "formControl", ""], ["input", "type", "checkbox", "ngModel", ""]], 85789 hostBindings: function CheckboxControlValueAccessor_HostBindings(rf, ctx) { 85790 if (rf & 1) { 85791 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("change", function CheckboxControlValueAccessor_change_HostBindingHandler($event) { 85792 return ctx.onChange($event.target.checked); 85793 })("blur", function CheckboxControlValueAccessor_blur_HostBindingHandler() { 85794 return ctx.onTouched(); 85795 }); 85796 } 85797 }, 85798 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([CHECKBOX_VALUE_ACCESSOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 85799}); 85800 85801(function () { 85802 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](CheckboxControlValueAccessor, [{ 85803 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 85804 args: [{ 85805 selector: 'input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]', 85806 host: { 85807 '(change)': 'onChange($event.target.checked)', 85808 '(blur)': 'onTouched()' 85809 }, 85810 providers: [CHECKBOX_VALUE_ACCESSOR] 85811 }] 85812 }], null, null); 85813})(); 85814/** 85815 * @license 85816 * Copyright Google LLC All Rights Reserved. 85817 * 85818 * Use of this source code is governed by an MIT-style license that can be 85819 * found in the LICENSE file at https://angular.io/license 85820 */ 85821 85822 85823const DEFAULT_VALUE_ACCESSOR = { 85824 provide: NG_VALUE_ACCESSOR, 85825 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => DefaultValueAccessor), 85826 multi: true 85827}; 85828/** 85829 * We must check whether the agent is Android because composition events 85830 * behave differently between iOS and Android. 85831 */ 85832 85833function _isAndroid() { 85834 const userAgent = (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__["ɵgetDOM"])() ? (0,_angular_common__WEBPACK_IMPORTED_MODULE_1__["ɵgetDOM"])().getUserAgent() : ''; 85835 return /android (\d+)/.test(userAgent.toLowerCase()); 85836} 85837/** 85838 * @description 85839 * Provide this token to control if form directives buffer IME input until 85840 * the "compositionend" event occurs. 85841 * @publicApi 85842 */ 85843 85844 85845const COMPOSITION_BUFFER_MODE = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('
85845CompositionEventMode'); 85846/** 85847 * The default `ControlValueAccessor` for writing a value and listening to changes on input 85848 * elements. The accessor is used by the `FormControlDirective`, `FormControlName`, and 85849 * `NgModel` directives. 85850 * 85851 * {@searchKeywords ngDefaultControl} 85852 * 85853 * @usageNotes 85854 * 85855 * ### Using the default value accessor 85856 * 85857 * The following example shows how to use an input element that activates the default value accessor 85858 * (in this case, a text field). 85859 * 85860 * ```ts 85861 * const firstNameControl = new FormControl(); 85862 * ``` 85863 * 85864 * ``` 85865 * <input type="text" [formControl]="firstNameControl"> 85866 * ``` 85867 * 85868 * This value accessor is used by default for `<input type="text">` and `<textarea>` elements, but 85869 * you could also use it for custom components that have similar behavior and do not require special 85870 * processing. In order to attach the default value accessor to a custom element, add the 85871 * `ngDefaultControl` attribute as shown below. 85872 * 85873 * ``` 85874 * <custom-input-component ngDefaultControl [(ngModel)]="value"></custom-input-component> 85875 * ``` 85876 * 85877 * @ngModule ReactiveFormsModule 85878 * @ngModule FormsModule 85879 * @publicApi 85880 */ 85881 85882class DefaultValueAccessor extends BaseControlValueAccessor { 85883 constructor(renderer, elementRef, _compositionMode) { 85884 super(renderer, elementRef); 85885 this._compositionMode = _compositionMode; 85886 /** Whether the user is creating a composition string (IME events). */ 85887 85888 this._composing = false; 85889 85890 if (this._compositionMode == null) { 85891 this._compositionMode = !_isAndroid(); 85892 } 85893 } 85894 /** 85895 * Sets the "value" property on the input element. 85896 * @nodoc 85897 */ 85898 85899 85900 writeValue(value) { 85901 const normalizedValue = value == null ? '' : value; 85902 this.setProperty('value', normalizedValue); 85903 } 85904 /** @internal */ 85905 85906 85907 _handleInput(value) { 85908 if (!this._compositionMode || this._compositionMode && !this._composing) { 85909 this.onChange(value); 85910 } 85911 } 85912 /** @internal */ 85913 85914 85915 _compositionStart() { 85916 this._composing = true; 85917 } 85918 /** @internal */ 85919 85920 85921 _compositionEnd(value) { 85922 this._composing = false; 85923 this._compositionMode && this.onChange(value); 85924 } 85925 85926} 85927 85928DefaultValueAccessor.ɵfac = function DefaultValueAccessor_Factory(t) { 85929 return new (t || DefaultValueAccessor)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](COMPOSITION_BUFFER_MODE, 8)); 85930}; 85931 85932DefaultValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 85933 type: DefaultValueAccessor, 85934 selectors: [["input", "formControlName", "", 3, "type", "checkbox"], ["textarea", "formControlName", ""], ["input", "formControl", "", 3, "type", "checkbox"], ["textarea", "formControl", ""], ["input", "ngModel", "", 3, "type", "checkbox"], ["textarea", "ngModel", ""], ["", "ngDefaultControl", ""]], 85935 hostBindings: function DefaultValueAccessor_HostBindings(rf, ctx) { 85936 if (rf & 1) { 85937 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("input", function DefaultValueAccessor_input_HostBindingHandler($event) { 85938 return ctx._handleInput($event.target.value); 85939 })("blur", function DefaultValueAccessor_blur_HostBindingHandler() { 85940 return ctx.onTouched(); 85941 })("compositionstart", function DefaultValueAccessor_compositionstart_HostBindingHandler() { 85942 return ctx._compositionStart(); 85943 })("compositionend", function DefaultValueAccessor_compositionend_HostBindingHandler($event) { 85944 return ctx._compositionEnd($event.target.value); 85945 }); 85946 } 85947 }, 85948 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([DEFAULT_VALUE_ACCESSOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 85949}); 85950 85951(function () { 85952 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](DefaultValueAccessor, [{ 85953 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 85954 args: [{ 85955 selector: 'input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]', 85956 // TODO: vsavkin replace the above selector with the one below it once 85957 // https://github.com/angular/angular/issues/3011 is implemented 85958 // selector: '[ngModel],[formControl],[formControlName]', 85959 host: { 85960 '(input)': '$any(this)._handleInput($event.target.value)', 85961 '(blur)': 'onTouched()', 85962 '(compositionstart)': '$any(this)._compositionStart()', 85963 '(compositionend)': '$any(this)._compositionEnd($event.target.value)' 85964 }, 85965 providers: [DEFAULT_VALUE_ACCESSOR] 85966 }] 85967 }], function () { 85968 return [{ 85969 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2 85970 }, {
85971 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef 85972 }, { 85973 type: undefined, 85974 decorators: [{ 85975 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 85976 }, { 85977 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 85978 args: [COMPOSITION_BUFFER_MODE] 85979 }] 85980 }]; 85981 }, null); 85982})(); 85983/** 85984 * @license 85985 * Copyright Google LLC All Rights Reserved. 85986 * 85987 * Use of this source code is governed by an MIT-style license that can be 85988 * found in the LICENSE file at https://angular.io/license 85989 */ 85990 85991 85992const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode; 85993 85994function isEmptyInputValue(value) { 85995 /** 85996 * Check if the object is a string or array before evaluating the length attribute. 85997 * This avoids falsely rejecting objects that contain a custom length attribute. 85998 * For example, the object {id: 1, length: 0, width: 0} should not be returned as empty. 85999 */ 86000 return value == null || (typeof value === 'string' || Array.isArray(value)) && value.length === 0; 86001} 86002 86003function hasValidLength(value) { 86004 // non-strict comparison is intentional, to check for both `null` and `undefined` values 86005 return value != null && typeof value.length === 'number'; 86006} 86007/** 86008 * @description 86009 * An `InjectionToken` for registering additional synchronous validators used with 86010 * `AbstractControl`s. 86011 * 86012 * @see `NG_ASYNC_VALIDATORS` 86013 * 86014 * @usageNotes 86015 * 86016 * ### Providing a custom validator 86017 * 86018 * The following example registers a custom validator directive. Adding the validator to the 86019 * existing collection of validators requires the `multi: true` option. 86020 * 86021 * ```typescript 86022 * @Directive({ 86023 * selector: '[customValidator]', 86024 * providers: [{provide: NG_VALIDATORS, useExisting: CustomValidatorDirective, multi: true}] 86025 * }) 86026 * class CustomValidatorDirective implements Validator { 86027 * validate(control: AbstractControl): ValidationErrors | null { 86028 * return { 'custom': true }; 86029 * } 86030 * } 86031 * ``` 86032 * 86033 * @publicApi 86034 */ 86035 86036 86037const NG_VALIDATORS = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('NgValidators'); 86038/** 86039 * @description 86040 * An `InjectionToken` for registering additional asynchronous validators used with 86041 * `AbstractControl`s. 86042 * 86043 * @see `NG_VALIDATORS` 86044 * 86045 * @usageNotes 86046 * 86047 * ### Provide a custom async validator directive 86048 * 86049 * The following example implements the `AsyncValidator` interface to create an 86050 * async validator directive with a custom error key. 86051 * 86052 * ```typescript 86053 * @Directive({ 86054 * selector: '[customAsyncValidator]', 86055 * providers: [{provide: NG_ASYNC_VALIDATORS, useExisting: CustomAsyncValidatorDirective, multi: 86056 * true}] 86057 * }) 86058 * class CustomAsyncValidatorDirective implements AsyncValidator { 86059 * validate(control: AbstractControl): Promise<ValidationErrors|null> { 86060 * return Promise.resolve({'custom': true}); 86061 * } 86062 * } 86063 * ``` 86064 * 86065 * @publicApi 86066 */ 86067 86068const NG_ASYNC_VALIDATORS = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('NgAsyncValidators'); 86069/** 86070 * A regular expression that matches valid e-mail addresses. 86071 * 86072 * At a high level, this regexp matches e-mail addresses of the format `local-part@tld`, where: 86073 * - `local-part` consists of one or more of the allowed characters (alphanumeric and some 86074 * punctuation symbols). 86075 * - `local-part` cannot begin or end with a period (`.`). 86076 * - `local-part` cannot be longer than 64 characters. 86077 * - `tld` consists of one or more `labels` separated by periods (`.`). For example `localhost` or 86078 * `foo.com`. 86079 * - A `label` consists of one or more of the allowed characters (alphanumeric, dashes (`-`) and 86080 * periods (`.`)). 86081 * - A `label` cannot begin or end with a dash (`-`) or a period (`.`). 86082 * - A `label` cannot be longer than 63 characters. 86083 * - The whole address cannot be longer than 254 characters. 86084 * 86085 * ## Implementation background 86086 * 86087 * This regexp was ported over from AngularJS (see there for git history): 86088 * https://github.com/angular/angular.js/blob/c133ef836/src/ng/directive/input.js#L27 86089 * It is based on the 86090 * [WHATWG version](https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address) with 86091 * some enhancements to incorporate more RFC rules (such as rules related to domain names and the 86092 * lengths of different parts of the address). The main differences from the WHATWG version are: 86093 * - Disallow `local-part` to begin or end with a period (`.`). 86094 * - Disallow `local-part` length to exceed 64 characters. 86095 * - Disallow total address length to exceed 254 characters. 86096 * 86097 * See [this commit](https://github.com/angular/angular.js/commit/f3f5cf72e) for more details. 86098 */ 86099 86100const EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; 86101/** 86102 * @description 86103 * Provides a set of built-in validators that can be used by form controls. 86104 *
86105 * A validator is a function that processes a `FormControl` or collection of 86106 * controls and returns an error map or null. A null map means that validation has passed. 86107 * 86108 * @see [Form Validation](/guide/form-validation) 86109 * 86110 * @publicApi 86111 */ 86112 86113class Validators { 86114 /** 86115 * @description 86116 * Validator that requires the control's value to be greater than or equal to the provided number. 86117 * 86118 * @usageNotes 86119 * 86120 * ### Validate against a minimum of 3 86121 * 86122 * ```typescript 86123 * const control = new FormControl(2, Validators.min(3)); 86124 * 86125 * console.log(control.errors); // {min: {min: 3, actual: 2}} 86126 * ``` 86127 * 86128 * @returns A validator function that returns an error map with the 86129 * `min` property if the validation check fails, otherwise `null`. 86130 * 86131 * @see `updateValueAndValidity()` 86132 * 86133 */ 86134 static min(min) { 86135 return minValidator(min); 86136 } 86137 /** 86138 * @description 86139 * Validator that requires the control's value to be less than or equal to the provided number. 86140 * 86141 * @usageNotes 86142 * 86143 * ### Validate against a maximum of 15 86144 * 86145 * ```typescript 86146 * const control = new FormControl(16, Validators.max(15)); 86147 * 86148 * console.log(control.errors); // {max: {max: 15, actual: 16}} 86149 * ``` 86150 * 86151 * @returns A validator function that returns an error map with the 86152 * `max` property if the validation check fails, otherwise `null`. 86153 * 86154 * @see `updateValueAndValidity()` 86155 * 86156 */ 86157 86158 86159 static max(max) { 86160 return maxValidator(max); 86161 } 86162 /** 86163 * @description 86164 * Validator that requires the control have a non-empty value. 86165 * 86166 * @usageNotes 86167 * 86168 * ### Validate that the field is non-empty 86169 * 86170 * ```typescript 86171 * const control = new FormControl('', Validators.required); 86172 * 86173 * console.log(control.errors); // {required: true} 86174 * ``` 86175 * 86176 * @returns An error map with the `required` property 86177 * if the validation check fails, otherwise `null`. 86178 * 86179 * @see `updateValueAndValidity()` 86180 * 86181 */ 86182 86183 86184 static required(control) { 86185 return requiredValidator(control); 86186 } 86187 /** 86188 * @description 86189 * Validator that requires the control's value be true. This validator is commonly 86190 * used for required checkboxes. 86191 * 86192 * @usageNotes 86193 * 86194 * ### Validate that the field value is true 86195 * 86196 * ```typescript 86197 * const control = new FormControl('some value', Validators.requiredTrue); 86198 * 86199 * console.log(control.errors); // {required: true} 86200 * ``` 86201 * 86202 * @returns An error map that contains the `required` property 86203 * set to `true` if the validation check fails, otherwise `null`. 86204 * 86205 * @see `updateValueAndValidity()` 86206 * 86207 */ 86208 86209 86210 static requiredTrue(control) { 86211 return requiredTrueValidator(control); 86212 } 86213 /** 86214 * @description 86215 * Validator that requires the control's value pass an email validation test. 86216 * 86217 * Tests the value using a [regular 86218 * expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) 86219 * pattern suitable for common use cases. The pattern is based on the definition of a valid email 86220 * address in the [WHATWG HTML 86221 * specification](https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address) with 86222 * some enhancements to incorporate more RFC rules (such as rules related to domain names and the 86223 * lengths of different parts of the address). 86224 * 86225 * The differences from the WHATWG version include: 86226 * - Disallow `local-part` (the part before the `@` symbol) to begin or end with a period (`.`). 86227 * - Disallow `local-part` to be longer than 64 characters. 86228 * - Disallow the whole address to be longer than 254 characters. 86229 * 86230 * If this pattern does not satisfy your business needs, you can use `Validators.pattern()` to 86231 * validate the value against a different pattern. 86232 * 86233 * @usageNotes 86234 * 86235 * ### Validate that the field matches a valid email pattern 86236 * 86237 * ```typescript 86238 * const control = new FormControl('bad@', Validators.email); 86239 * 86240 * console.log(control.errors); // {email: true} 86241 * ``` 86242 * 86243 * @returns An error map with the `email` property 86244 * if the validation check fails, otherwise `null`. 86245 *
86246 * @see `updateValueAndValidity()` 86247 * 86248 */ 86249 86250 86251 static email(control) { 86252 return emailValidator(control); 86253 } 86254 /** 86255 * @description 86256 * Validator that requires the length of the control's value to be greater than or equal 86257 * to the provided minimum length. This validator is also provided by default if you use the 86258 * the HTML5 `minlength` attribute. Note that the `minLength` validator is intended to be used 86259 * only for types that have a numeric `length` property, such as strings or arrays. The 86260 * `minLength` validator logic is also not invoked for values when their `length` property is 0 86261 * (for example in case of an empty string or an empty array), to support optional controls. You 86262 * can use the standard `required` validator if empty values should not be considered valid. 86263 * 86264 * @usageNotes 86265 * 86266 * ### Validate that the field has a minimum of 3 characters 86267 * 86268 * ```typescript 86269 * const control = new FormControl('ng', Validators.minLength(3)); 86270 * 86271 * console.log(control.errors); // {minlength: {requiredLength: 3, actualLength: 2}} 86272 * ``` 86273 * 86274 * ```html 86275 * <input minlength="5"> 86276 * ``` 86277 * 86278 * @returns A validator function that returns an error map with the 86279 * `minlength` property if the validation check fails, otherwise `null`. 86280 * 86281 * @see `updateValueAndValidity()` 86282 * 86283 */ 86284 86285 86286 static minLength(minLength) { 86287 return minLengthValidator(minLength); 86288 } 86289 /** 86290 * @description 86291 * Validator that requires the length of the control's value to be less than or equal 86292 * to the provided maximum length. This validator is also provided by default if you use the 86293 * the HTML5 `maxlength` attribute. Note that the `maxLength` validator is intended to be used 86294 * only for types that have a numeric `length` property, such as strings or arrays. 86295 * 86296 * @usageNotes 86297 * 86298 * ### Validate that the field has maximum of 5 characters 86299 * 86300 * ```typescript 86301 * const control = new FormControl('Angular', Validators.maxLength(5)); 86302 * 86303 * console.log(control.errors); // {maxlength: {requiredLength: 5, actualLength: 7}} 86304 * ``` 86305 * 86306 * ```html 86307 * <input maxlength="5"> 86308 * ``` 86309 * 86310 * @returns A validator function that returns an error map with the 86311 * `maxlength` property if the validation check fails, otherwise `null`. 86312 * 86313 * @see `updateValueAndValidity()` 86314 * 86315 */ 86316 86317 86318 static maxLength(maxLength) { 86319 return maxLengthValidator(maxLength); 86320 } 86321 /** 86322 * @description 86323 * Validator that requires the control's value to match a regex pattern. This validator is also 86324 * provided by default if you use the HTML5 `pattern` attribute. 86325 * 86326 * @usageNotes 86327 * 86328 * ### Validate that the field only contains letters or spaces 86329 * 86330 * ```typescript 86331 * const control = new FormControl('1', Validators.pattern('[a-zA-Z ]*')); 86332 * 86333 * console.log(control.errors); // {pattern: {requiredPattern: '^[a-zA-Z ]*$', actualValue: '1'}} 86334 * ``` 86335 * 86336 * ```html 86337 * <input pattern="[a-zA-Z ]*"> 86338 * ``` 86339 * 86340 * ### Pattern matching with the global or sticky flag 86341 * 86342 * `RegExp` objects created with the `g` or `y` flags that are passed into `Validators.pattern` 86343 * can produce different results on the same input when validations are run consecutively. This is 86344 * due to how the behavior of `RegExp.prototype.test` is 86345 * specified in [ECMA-262](https://tc39.es/ecma262/#sec-regexpbuiltinexec) 86346 * (`RegExp` preserves the index of the last match when the global or sticky flag is used). 86347 * Due to this behavior, it is recommended that when using 86348 * `Validators.pattern` you **do not** pass in a `RegExp` object with either the global or sticky 86349 * flag enabled. 86350 * 86351 * ```typescript 86352 * // Not recommended (since the `g` flag is used) 86353 * const controlOne = new FormControl('1', Validators.pattern(/foo/g)); 86354 * 86355 * // Good 86356 * const controlTwo = new FormControl('1', Validators.pattern(/foo/)); 86357 * ``` 86358 * 86359 * @param pattern A regular expression to be used as is to test the values, or a string. 86360 * If a string is passed, the `^` character is prepended and the `$` character is 86361 * appended to the provided string (if not already present), and the resulting regular 86362 * expression is used to test the values. 86363 * 86364 * @returns A validator function that returns an error map with the 86365 * `pattern` property if the validation check fails, otherwise `null`. 86366 *
vendor: 4,278 bytes, lines 86367-86525
86367 * @see `updateValueAndValidity()` 86368 * 86369 */ 86370 86371 86372 static pattern(pattern) { 86373 return patternValidator(pattern); 86374 } 86375 /** 86376 * @description 86377 * Validator that performs no operation. 86378 * 86379 * @see `updateValueAndValidity()` 86380 * 86381 */ 86382 86383 86384 static nullValidator(control) { 86385 return nullValidator(control); 86386 } 86387 86388 static compose(validators) { 86389 return compose(validators); 86390 } 86391 /** 86392 * @description 86393 * Compose multiple async validators into a single function that returns the union 86394 * of the individual error objects for the provided control. 86395 * 86396 * @returns A validator function that returns an error map with the 86397 * merged error objects of the async validators if the validation check fails, otherwise `null`. 86398 * 86399 * @see `updateValueAndValidity()` 86400 * 86401 */ 86402 86403 86404 static composeAsync(validators) { 86405 return composeAsync(validators); 86406 } 86407 86408} 86409/** 86410 * Validator that requires the control's value to be greater than or equal to the provided number. 86411 * See `Validators.min` for additional information. 86412 */ 86413 86414 86415function minValidator(min) { 86416 return control => { 86417 if (isEmptyInputValue(control.value) || isEmptyInputValue(min)) { 86418 return null; // don't validate empty values to allow optional controls 86419 } 86420 86421 const value = parseFloat(control.value); // Controls with NaN values after parsing should be treated as not having a 86422 // minimum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-min 86423 86424 return !isNaN(value) && value < min ? { 86425 'min': { 86426 'min': min, 86427 'actual': control.value 86428 } 86429 } : null; 86430 }; 86431} 86432/** 86433 * Validator that requires the control's value to be less than or equal to the provided number. 86434 * See `Validators.max` for additional information. 86435 */ 86436 86437 86438function maxValidator(max) { 86439 return control => { 86440 if (isEmptyInputValue(control.value) || isEmptyInputValue(max)) { 86441 return null; // don't validate empty values to allow optional controls 86442 } 86443 86444 const value = parseFloat(control.value); // Controls with NaN values after parsing should be treated as not having a 86445 // maximum, per the HTML forms spec: https://www.w3.org/TR/html5/forms.html#attr-input-max 86446 86447 return !isNaN(value) && value > max ? { 86448 'max': { 86449 'max': max, 86450 'actual': control.value 86451 } 86452 } : null; 86453 }; 86454} 86455/** 86456 * Validator that requires the control have a non-empty value. 86457 * See `Validators.required` for additional information. 86458 */ 86459 86460 86461function requiredValidator(control) { 86462 return isEmptyInputValue(control.value) ? { 86463 'required': true 86464 } : null; 86465} 86466/** 86467 * Validator that requires the control's value be true. This validator is commonly 86468 * used for required checkboxes. 86469 * See `Validators.requiredTrue` for additional information. 86470 */ 86471 86472 86473function requiredTrueValidator(control) { 86474 return control.value === true ? null : { 86475 'required': true 86476 }; 86477} 86478/** 86479 * Validator that requires the control's value pass an email validation test. 86480 * See `Validators.email` for additional information. 86481 */ 86482 86483 86484function emailValidator(control) { 86485 if (isEmptyInputValue(control.value)) { 86486 return null; // don't validate empty values to allow optional controls 86487 } 86488 86489 return EMAIL_REGEXP.test(control.value) ? null : { 86490 'email': true 86491 }; 86492} 86493/** 86494 * Validator that requires the length of the control's value to be greater than or equal 86495 * to the provided minimum length. See `Validators.minLength` for additional information. 86496 */ 86497 86498 86499function minLengthValidator(minLength) { 86500 return control => { 86501 if (isEmptyInputValue(control.value) || !hasValidLength(control.value)) { 86502 // don't validate empty values to allow optional controls 86503 // don't validate values without `length` property 86504 return null; 86505 } 86506 86507 return control.value.length < minLength ? { 86508 'minlength': { 86509 'requiredLength': minLength, 86510 'actualLength': control.value.length 86511 } 86512 } : null; 86513 }; 86514} 86515/** 86516 * Validator that requires the length of the control's value to be less than or equal 86517 * to the provided maximum length. See `Validators.maxLength` for additional information. 86518 */ 86519 86520 86521function maxLengthValidator(maxLength) { 86522 return control => { 86523 return hasValidLength(control.value) && control.value.length > maxLength ? { 86524 'maxlength': { 86525 'requiredLength': maxLength,
86526 'actualLength': control.value.length 86527 } 86528 } : null; 86529 }; 86530} 86531/** 86532 * Validator that requires the control's value to match a regex pattern. 86533 * See `Validators.pattern` for additional information. 86534 */ 86535 86536 86537function patternValidator(pattern) { 86538 if (!pattern) return nullValidator; 86539 let regex; 86540 let regexStr; 86541 86542 if (typeof pattern === 'string') { 86543 regexStr = ''; 86544 if (pattern.charAt(0) !== '^') regexStr += '^'; 86545 regexStr += pattern; 86546 if (pattern.charAt(pattern.length - 1) !== '$') regexStr += '$'; 86547 regex = new RegExp(regexStr); 86548 } else { 86549 regexStr = pattern.toString(); 86550 regex = pattern; 86551 } 86552 86553 return control => { 86554 if (isEmptyInputValue(control.value)) { 86555 return null; // don't validate empty values to allow optional controls 86556 } 86557 86558 const value = control.value; 86559 return regex.test(value) ? null : { 86560 'pattern': { 86561 'requiredPattern': regexStr, 86562 'actualValue': value 86563 } 86564 }; 86565 }; 86566} 86567/** 86568 * Function that has `ValidatorFn` shape, but performs no operation. 86569 */ 86570 86571 86572function nullValidator(control) { 86573 return null; 86574} 86575 86576function isPresent(o) { 86577 return o != null; 86578} 86579 86580function toObservable(value) { 86581 const obs = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisPromise"])(value) ? (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.from)(value) : value; 86582 86583 if (NG_DEV_MODE$1 && !(0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisObservable"])(obs)) { 86584 let errorMessage = `Expected async validator to return Promise or Observable.`; // A synchronous validator will return object or null. 86585 86586 if (typeof value === 'object') { 86587 errorMessage += ' Are you using a synchronous validator where an async validator is expected?'; 86588 } 86589 86590 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](-1101 86591 /* RuntimeErrorCode.WRONG_VALIDATOR_RETURN_TYPE */ 86592 , errorMessage); 86593 } 86594 86595 return obs; 86596} 86597 86598function mergeErrors(arrayOfErrors) { 86599 let res = {}; // Not using Array.reduce here due to a Chrome 80 bug 86600 // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982 86601 86602 arrayOfErrors.forEach(errors => { 86603 res = errors != null ? { ...res, 86604 ...errors 86605 } : res; 86606 }); 86607 return Object.keys(res).length === 0 ? null : res; 86608} 86609 86610function executeValidators(control, validators) { 86611 return validators.map(validator => validator(control)); 86612} 86613 86614function isValidatorFn(validator) { 86615 return !validator.validate; 86616} 86617/** 86618 * Given the list of validators that may contain both functions as well as classes, return the list 86619 * of validator functions (convert validator classes into validator functions). This is needed to 86620 * have consistent structure in validators list before composing them. 86621 * 86622 * @param validators The set of validators that may contain validators both in plain function form 86623 * as well as represented as a validator class. 86624 */ 86625 86626 86627function normalizeValidators(validators) { 86628 return validators.map(validator => { 86629 return isValidatorFn(validator) ? validator : c => validator.validate(c); 86630 }); 86631} 86632/** 86633 * Merges synchronous validators into a single validator function. 86634 * See `Validators.compose` for additional information. 86635 */ 86636 86637 86638function compose(validators) { 86639 if (!validators) return null; 86640 const presentValidators = validators.filter(isPresent); 86641 if (presentValidators.length == 0) return null; 86642 return function (control) { 86643 return mergeErrors(executeValidators(control, presentValidators)); 86644 }; 86645} 86646/** 86647 * Accepts a list of validators of different possible shapes (`Validator` and `ValidatorFn`), 86648 * normalizes the list (converts everything to `ValidatorFn`) and merges them into a single 86649 * validator function. 86650 */ 86651 86652 86653function composeValidators(validators) { 86654 return validators != null ? compose(normalizeValidators(validators)) : null; 86655} 86656/** 86657 * Merges asynchronous validators into a single validator function. 86658 * See `Validators.composeAsync` for additional information. 86659 */ 86660 86661 86662function composeAsync(validators) { 86663 if (!validators) return null; 86664 const presentValidators = validators.filter(isPresent); 86665 if (presentValidators.length == 0) return null; 86666 return function (control) { 86667 const observables = executeValidators(control, presentValidators).map(toObservable); 86668 return (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.forkJoin)(observables).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(mergeErrors)); 86669 }; 86670} 86671/** 86672 * Accepts a list of async validators of different possible shapes (`AsyncValidator` and 86673 * `AsyncValidatorFn`), normalizes the list (converts everything to `AsyncValidatorFn`) and merges 86674 * them into a single validator function. 86675 */ 86676 86677 86678function composeAsyncValidators(validators) { 86679 return validators != null ? composeAsync(normalizeValidators(validators)) : null; 86680} 86681/** 86682 * Merges raw control validators with a given directive validator and returns the combined list of 86683 * validators as an array.
86684 */ 86685 86686 86687function mergeValidators(controlValidators, dirValidator) { 86688 if (controlValidators === null) return [dirValidator]; 86689 return Array.isArray(controlValidators) ? [...controlValidators, dirValidator] : [controlValidators, dirValidator]; 86690} 86691/** 86692 * Retrieves the list of raw synchronous validators attached to a given control. 86693 */ 86694 86695 86696function getControlValidators(control) { 86697 return control._rawValidators; 86698} 86699/** 86700 * Retrieves the list of raw asynchronous validators attached to a given control. 86701 */ 86702 86703 86704function getControlAsyncValidators(control) { 86705 return control._rawAsyncValidators; 86706} 86707/** 86708 * Accepts a singleton validator, an array, or null, and returns an array type with the provided 86709 * validators. 86710 * 86711 * @param validators A validator, validators, or null. 86712 * @returns A validators array. 86713 */ 86714 86715 86716function makeValidatorsArray(validators) { 86717 if (!validators) return []; 86718 return Array.isArray(validators) ? validators : [validators]; 86719} 86720/** 86721 * Determines whether a validator or validators array has a given validator. 86722 * 86723 * @param validators The validator or validators to compare against. 86724 * @param validator The validator to check. 86725 * @returns Whether the validator is present. 86726 */ 86727 86728 86729function hasValidator(validators, validator) { 86730 return Array.isArray(validators) ? validators.includes(validator) : validators === validator; 86731} 86732/** 86733 * Combines two arrays of validators into one. If duplicates are provided, only one will be added. 86734 * 86735 * @param validators The new validators. 86736 * @param currentValidators The base array of current validators. 86737 * @returns An array of validators. 86738 */ 86739 86740 86741function addValidators(validators, currentValidators) { 86742 const current = makeValidatorsArray(currentValidators); 86743 const validatorsToAdd = makeValidatorsArray(validators); 86744 validatorsToAdd.forEach(v => { 86745 // Note: if there are duplicate entries in the new validators array, 86746 // only the first one would be added to the current list of validators. 86747 // Duplicate ones would be ignored since `hasValidator` would detect 86748 // the presence of a validator function and we update the current list in place. 86749 if (!hasValidator(current, v)) { 86750 current.push(v); 86751 } 86752 }); 86753 return current; 86754} 86755 86756function removeValidators(validators, currentValidators) { 86757 return makeValidatorsArray(currentValidators).filter(v => !hasValidator(validators, v)); 86758} 86759/** 86760 * @license 86761 * Copyright Google LLC All Rights Reserved. 86762 * 86763 * Use of this source code is governed by an MIT-style license that can be 86764 * found in the LICENSE file at https://angular.io/license 86765 */ 86766 86767/** 86768 * @description 86769 * Base class for control directives. 86770 * 86771 * This class is only used internally in the `ReactiveFormsModule` and the `FormsModule`. 86772 * 86773 * @publicApi 86774 */ 86775 86776 86777class AbstractControlDirective { 86778 constructor() { 86779 /** 86780 * Set of synchronous validators as they were provided while calling `setValidators` function. 86781 * @internal 86782 */ 86783 this._rawValidators = []; 86784 /** 86785 * Set of asynchronous validators as they were provided while calling `setAsyncValidators` 86786 * function. 86787 * @internal 86788 */ 86789 86790 this._rawAsyncValidators = []; 86791 /* 86792 * The set of callbacks to be invoked when directive instance is being destroyed. 86793 */ 86794 86795 this._onDestroyCallbacks = []; 86796 } 86797 /** 86798 * @description 86799 * Reports the value of the control if it is present, otherwise null. 86800 */ 86801 86802 86803 get value() { 86804 return this.control ? this.control.value : null; 86805 } 86806 /** 86807 * @description 86808 * Reports whether the control is valid. A control is considered valid if no 86809 * validation errors exist with the current value. 86810 * If the control is not present, null is returned. 86811 */ 86812 86813 86814 get valid() { 86815 return this.control ? this.control.valid : null; 86816 } 86817 /** 86818 * @description 86819 * Reports whether the control is invalid, meaning that an error exists in the input value. 86820 * If the control is not present, null is returned. 86821 */ 86822 86823 86824 get invalid() { 86825 return this.control ? this.control.invalid : null; 86826 } 86827 /** 86828 * @description 86829 * Reports whether a control is pending, meaning that that async validation is occurring and 86830 * errors are not yet available for the input value. If the control is not present, null is 86831 * returned. 86832 */ 86833 86834 86835 get pending() { 86836 return this.control ? this.control.pending : null; 86837 } 86838 /** 86839 * @description 86840 * Reports whether the control is disabled, meaning that the control is disabled 86841 * in the UI and is exempt from validation checks and excluded from aggregate 86842 * values of ancestor controls. If the control is not present, null is returned. 86843 */ 86844 86845 86846 get disabled() { 86847 return this.control ? this.control.disabled : null; 86848 } 86849 /** 86850 * @description 86851 * Reports whether the control is enabled, meaning that the control is included in ancestor 86852 * calculations of validity or value. If the control is not present, null is returned. 86853 */ 86854 86855 86856 get enabled() { 86857 return this.control ? this.control.enabled : null; 86858 } 86859 /** 86860 * @description 86861 * Reports the control's validation errors. If the control is not present, null is returned. 86862 */ 86863 86864 86865 get errors() { 86866 return this.control ? this.control.errors : null; 86867 } 86868 /** 86869 * @description 86870 * Reports whether the control is pristine, meaning that the user has not yet changed 86871 * the value in the UI. If the control is not present, null is returned. 86872 */ 86873 86874 86875 get pristine() { 86876 return this.control ? this.control.pristine : null; 86877 } 86878 /** 86879 * @description 86880 * Reports whether the control is dirty, meaning that the user has changed 86881 * the value in the UI. If the control is not present, null is returned. 86882 */ 86883 86884 86885 get dirty() { 86886 return this.control ? this.control.dirty : null; 86887 } 86888 /** 86889 * @description 86890 * Reports whether the control is touched, meaning that the user has triggered 86891 * a `blur` event on it. If the control is not present, null is returned. 86892 */ 86893 86894 86895 get touched() { 86896 return this.control ? this.control.touched : null; 86897 } 86898 /** 86899 * @description 86900 * Reports the validation status of the control. Possible values include:
86901 * 'VALID', 'INVALID', 'DISABLED', and 'PENDING'. 86902 * If the control is not present, null is returned. 86903 */ 86904 86905 86906 get status() { 86907 return this.control ? this.control.status : null; 86908 } 86909 /** 86910 * @description 86911 * Reports whether the control is untouched, meaning that the user has not yet triggered 86912 * a `blur` event on it. If the control is not present, null is returned. 86913 */ 86914 86915 86916 get untouched() { 86917 return this.control ? this.control.untouched : null; 86918 } 86919 /** 86920 * @description 86921 * Returns a multicasting observable that emits a validation status whenever it is 86922 * calculated for the control. If the control is not present, null is returned. 86923 */ 86924 86925 86926 get statusChanges() { 86927 return this.control ? this.control.statusChanges : null; 86928 } 86929 /** 86930 * @description 86931 * Returns a multicasting observable of value changes for the control that emits every time the 86932 * value of the control changes in the UI or programmatically. 86933 * If the control is not present, null is returned. 86934 */ 86935 86936 86937 get valueChanges() { 86938 return this.control ? this.control.valueChanges : null; 86939 } 86940 /** 86941 * @description 86942 * Returns an array that represents the path from the top-level form to this control. 86943 * Each index is the string name of the control on that level. 86944 */ 86945 86946 86947 get path() { 86948 return null; 86949 } 86950 /** 86951 * Sets synchronous validators for this directive. 86952 * @internal 86953 */ 86954 86955 86956 _setValidators(validators) { 86957 this._rawValidators = validators || []; 86958 this._composedValidatorFn = composeValidators(this._rawValidators); 86959 } 86960 /** 86961 * Sets asynchronous validators for this directive. 86962 * @internal 86963 */ 86964 86965 86966 _setAsyncValidators(validators) { 86967 this._rawAsyncValidators = validators || []; 86968 this._composedAsyncValidatorFn = composeAsyncValidators(this._rawAsyncValidators); 86969 } 86970 /** 86971 * @description 86972 * Synchronous validator function composed of all the synchronous validators registered with this 86973 * directive. 86974 */ 86975 86976 86977 get validator() { 86978 return this._composedValidatorFn || null; 86979 } 86980 /** 86981 * @description 86982 * Asynchronous validator function composed of all the asynchronous validators registered with 86983 * this directive. 86984 */ 86985 86986 86987 get asyncValidator() { 86988 return this._composedAsyncValidatorFn || null; 86989 } 86990 /** 86991 * Internal function to register callbacks that should be invoked 86992 * when directive instance is being destroyed. 86993 * @internal 86994 */ 86995 86996 86997 _registerOnDestroy(fn) { 86998 this._onDestroyCallbacks.push(fn); 86999 } 87000 /** 87001 * Internal function to invoke all registered "on destroy" callbacks. 87002 * Note: calling this function also clears the list of callbacks. 87003 * @internal 87004 */ 87005 87006 87007 _invokeOnDestroyCallbacks() { 87008 this._onDestroyCallbacks.forEach(fn => fn()); 87009 87010 this._onDestroyCallbacks = []; 87011 } 87012 /** 87013 * @description 87014 * Resets the control with the provided value if the control is present. 87015 */ 87016 87017 87018 reset(value = undefined) { 87019 if (this.control) this.control.reset(value); 87020 } 87021 /** 87022 * @description 87023 * Reports whether the control with the given path has the error specified. 87024 * 87025 * @param errorCode The code of the error to check 87026 * @param path A list of control names that designates how to move from the current control 87027 * to the control that should be queried for errors. 87028 * 87029 * @usageNotes 87030 * For example, for the following `FormGroup`: 87031 * 87032 * ``` 87033 * form = new FormGroup({ 87034 * address: new FormGroup({ street: new FormControl() }) 87035 * }); 87036 * ``` 87037 * 87038 * The path to the 'street' control from the root form would be 'address' -> 'street'. 87039 * 87040 * It can be provided to this method in one of two formats: 87041 * 87042 * 1. An array of string control names, e.g. `['address', 'street']` 87043 * 1. A period-delimited list of control names in one string, e.g. `'address.street'` 87044 * 87045 * If no path is given, this method checks for the error on the current control. 87046 * 87047 * @returns whether the given error is present in the control at the given path. 87048 * 87049 * If the control is not present, false is returned. 87050 */ 87051 87052 87053 hasError(errorCode, path) { 87054 return this.control ? this.control.hasError(errorCode, path) : false;
87055 } 87056 /** 87057 * @description 87058 * Reports error data for the control with the given path. 87059 * 87060 * @param errorCode The code of the error to check 87061 * @param path A list of control names that designates how to move from the current control 87062 * to the control that should be queried for errors. 87063 * 87064 * @usageNotes 87065 * For example, for the following `FormGroup`: 87066 * 87067 * ``` 87068 * form = new FormGroup({ 87069 * address: new FormGroup({ street: new FormControl() }) 87070 * }); 87071 * ``` 87072 * 87073 * The path to the 'street' control from the root form would be 'address' -> 'street'. 87074 * 87075 * It can be provided to this method in one of two formats: 87076 * 87077 * 1. An array of string control names, e.g. `['address', 'street']` 87078 * 1. A period-delimited list of control names in one string, e.g. `'address.street'` 87079 * 87080 * @returns error data for that particular error. If the control or error is not present, 87081 * null is returned. 87082 */ 87083 87084 87085 getError(errorCode, path) { 87086 return this.control ? this.control.getError(errorCode, path) : null; 87087 } 87088 87089} 87090/** 87091 * @license 87092 * Copyright Google LLC All Rights Reserved. 87093 * 87094 * Use of this source code is governed by an MIT-style license that can be 87095 * found in the LICENSE file at https://angular.io/license 87096 */ 87097 87098/** 87099 * @description 87100 * A base class for directives that contain multiple registered instances of `NgControl`. 87101 * Only used by the forms module. 87102 * 87103 * @publicApi 87104 */ 87105 87106 87107class ControlContainer extends AbstractControlDirective { 87108 /** 87109 * @description 87110 * The top-level form directive for the control. 87111 */ 87112 get formDirective() { 87113 return null; 87114 } 87115 /** 87116 * @description 87117 * The path to this group. 87118 */ 87119 87120 87121 get path() { 87122 return null; 87123 } 87124 87125} 87126/** 87127 * @license 87128 * Copyright Google LLC All Rights Reserved. 87129 * 87130 * Use of this source code is governed by an MIT-style license that can be 87131 * found in the LICENSE file at https://angular.io/license 87132 */ 87133 87134/** 87135 * @description 87136 * A base class that all `FormControl`-based directives extend. It binds a `FormControl` 87137 * object to a DOM element. 87138 * 87139 * @publicApi 87140 */ 87141 87142 87143class NgControl extends AbstractControlDirective { 87144 constructor() { 87145 super(...arguments); 87146 /** 87147 * @description 87148 * The parent form for the control. 87149 * 87150 * @internal 87151 */ 87152 87153 this._parent = null; 87154 /** 87155 * @description 87156 * The name for the control 87157 */ 87158 87159 this.name = null; 87160 /** 87161 * @description 87162 * The value accessor for the control 87163 */ 87164 87165 this.valueAccessor = null; 87166 } 87167 87168} 87169/** 87170 * @license 87171 * Copyright Google LLC All Rights Reserved. 87172 * 87173 * Use of this source code is governed by an MIT-style license that can be 87174 * found in the LICENSE file at https://angular.io/license 87175 */ 87176// DO NOT REFACTOR! 87177// Each status is represented by a separate function to make sure that 87178// advanced Closure Compiler optimizations related to property renaming 87179// can work correctly. 87180 87181 87182class AbstractControlStatus { 87183 constructor(cd) { 87184 this._cd = cd; 87185 } 87186 87187 get isTouched() { 87188 return !!this._cd?.control?.touched; 87189 } 87190 87191 get isUntouched() { 87192 return !!this._cd?.control?.untouched; 87193 } 87194 87195 get isPristine() { 87196 return !!this._cd?.control?.pristine; 87197 } 87198 87199 get isDirty() { 87200 return !!this._cd?.control?.dirty; 87201 } 87202 87203 get isValid() { 87204 return !!this._cd?.control?.valid; 87205 } 87206 87207 get isInvalid() { 87208 return !!this._cd?.control?.invalid; 87209 } 87210 87211 get isPending() { 87212 return !!this._cd?.control?.pending; 87213 } 87214 87215 get isSubmitted() { 87216 // We check for the `submitted` field from `NgForm` and `FormGroupDirective` classes, but 87217 // we avoid instanceof checks to prevent non-tree-shakable references to those types. 87218 return !!this._cd?.submitted; 87219 } 87220 87221} 87222 87223const ngControlStatusHost = { 87224 '[class.ng-untouched]': 'isUntouched', 87225 '[class.ng-touched]': 'isTouched', 87226 '[class.ng-pristine]': 'isPristine', 87227 '[class.ng-dirty]': 'isDirty', 87228 '[class.ng-valid]': 'isValid', 87229 '[class.ng-invalid]': 'isInvalid', 87230 '[class.ng-pending]': 'isPending' 87231}; 87232const ngGroupStatusHost = { ...ngControlStatusHost, 87233 '[class.ng-submitted]': 'isSubmitted' 87234}; 87235/** 87236 * @description 87237 * Directive automatically applied to Angular form controls that sets CSS classes 87238 * based on control status. 87239 * 87240 * @usageNotes 87241 * 87242 * ### CSS classes applied 87243 * 87244 * The following classes are applied as the properties become true: 87245 * 87246 * * ng-valid 87247 * * ng-invalid 87248 * * ng-pending 87249 * * ng-pristine 87250 * * ng-dirty 87251 * * ng-untouched 87252 * * ng-touched 87253 * 87254 * @ngModule ReactiveFormsModule 87255 * @ngModule FormsModule 87256 * @publicApi 87257 */ 87258 87259class NgControlStatus extends AbstractControlStatus { 87260 constructor(cd) { 87261 super(cd); 87262 } 87263 87264} 87265 87266NgControlStatus.ɵfac = function NgControlStatus_Factory(t) { 87267 return new (t || NgControlStatus)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NgControl, 2)); 87268}; 87269 87270NgControlStatus.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 87271 type: NgControlStatus, 87272 selectors: [["", "formControlName", ""], ["", "ngModel", ""], ["", "formControl", ""]], 87273 hostVars: 14, 87274 hostBindings: function NgControlStatus_HostBindings(rf, ctx) { 87275 if (rf & 2) { 87276 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵclassProp"]("ng-untouched", ctx.isUntouched)("ng-touched", ctx.isTouched)("ng-pristine", ctx.isPristine)("ng-dirty", ctx.isDirty)("ng-valid", ctx.isValid)("ng-invalid", ctx.isInvalid)("ng-pending", ctx.isPending); 87277 } 87278 }, 87279 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 87280}); 87281 87282(function () { 87283 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgControlStatus, [{ 87284 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 87285 args: [{ 87286 selector: '[formControlName],[ngModel],[formControl]', 87287 host: ngControlStatusHost 87288 }] 87289 }], function () { 87290 return [{ 87291 type: NgControl, 87292 decorators: [{ 87293 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 87294 }] 87295 }]; 87296 }, null); 87297})(); 87298/** 87299 * @description 87300 * Directive automatically applied to Angular form groups that sets CSS classes 87301 * based on control status (valid/invalid/dirty/etc). On groups, this includes the additional 87302 * class ng-submitted. 87303 * 87304 * @see `NgControlStatus` 87305 * 87306 * @ngModule ReactiveFormsModule 87307 * @ngModule FormsModule 87308 * @publicApi 87309 */ 87310 87311 87312class NgControlStatusGroup extends AbstractControlStatus { 87313 constructor(cd) { 87314 super(cd); 87315 } 87316 87317} 87318 87319NgControlStatusGroup.ɵfac = function NgControlStatusGroup_Factory(t) { 87320 return new (t || NgControlStatusGroup)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ControlContainer, 10)); 87321}; 87322 87323NgControlStatusGroup.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 87324 type: NgControlStatusGroup, 87325 selectors: [["", "formGroupName", ""], ["", "formArrayName", ""], ["", "ngModelGroup", ""], ["", "formGroup", ""], ["form", 3, "ngNoForm", ""], ["", "ngForm", ""]], 87326 hostVars: 16, 87327 hostBindings: function NgControlStatusGroup_HostBindings(rf, ctx) { 87328 if (rf & 2) { 87329 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵclassProp"]("ng-untouched", ctx.isUntouched)("ng-touched", ctx.isTouched)("ng-pristine", ctx.isPristine)("ng-dirty", ctx.isDirty)("ng-valid", ctx.isValid)("ng-invalid", ctx.isInvalid)("ng-pending", ctx.isPending)("ng-submitted", ctx.isSubmitted); 87330 } 87331 }, 87332 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 87333}); 87334 87335(function () { 87336 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgControlStatusGroup, [{ 87337 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 87338 args: [{ 87339 selector: '[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]', 87340 host: ngGroupStatusHost 87341 }] 87342 }], function () { 87343 return [{ 87344 type: ControlContainer, 87345 decorators: [{ 87346 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 87347 }, { 87348 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 87349 }] 87350 }]; 87351 }, null); 87352})(); 87353/** 87354 * @license 87355 * Copyright Google LLC All Rights Reserved. 87356 * 87357 * Use of this source code is governed by an MIT-style license that can be 87358 * found in the LICENSE file at https://angular.io/license 87359 */ 87360 87361 87362const formControlNameExample = ` 87363 <div [formGroup]="myGroup"> 87364 <input formControlName="firstName"> 87365 </div> 87366 87367 In your class: 87368 87369 this.myGroup = new FormGroup({ 87370 firstName: new FormControl() 87371 });`; 87372const formGroupNameExample = ` 87373 <div [formGroup]="myGroup"> 87374 <div formGroupName="person"> 87375 <input formControlName="firstName"> 87376 </div> 87377 </div> 87378 87379 In your class: 87380 87381 this.myGroup = new FormGroup({ 87382 person: new FormGroup({ firstName: new FormControl() }) 87383 });`; 87384const formArrayNameExample = ` 87385 <div [formGroup]="myGroup">
87386 <div formArrayName="cities"> 87387 <div *ngFor="let city of cityArray.controls; index as i"> 87388 <input [formControlName]="i"> 87389 </div> 87390 </div> 87391 </div> 87392 87393 In your class: 87394 87395 this.cityArray = new FormArray([new FormControl('SF')]); 87396 this.myGroup = new FormGroup({ 87397 cities: this.cityArray 87398 });`; 87399const ngModelGroupExample = ` 87400 <form> 87401 <div ngModelGroup="person"> 87402 <input [(ngModel)]="person.name" name="firstName"> 87403 </div> 87404 </form>`; 87405const ngModelWithFormGroupExample = ` 87406 <div [formGroup]="myGroup"> 87407 <input formControlName="firstName"> 87408 <input [(ngModel)]="showMoreControls" [ngModelOptions]="{standalone: true}"> 87409 </div> 87410`; 87411/** 87412 * @license 87413 * Copyright Google LLC All Rights Reserved. 87414 * 87415 * Use of this source code is governed by an MIT-style license that can be 87416 * found in the LICENSE file at https://angular.io/license 87417 */ 87418 87419function controlParentException() { 87420 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1050 87421 /* RuntimeErrorCode.FORM_CONTROL_NAME_MISSING_PARENT */ 87422 , `formControlName must be used with a parent formGroup directive. You'll want to add a formGroup 87423 directive and pass it an existing FormGroup instance (you can create one in your class). 87424 87425 Example: 87426 87427 ${formControlNameExample}`); 87428} 87429 87430function ngModelGroupException() { 87431 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1051 87432 /* RuntimeErrorCode.FORM_CONTROL_NAME_INSIDE_MODEL_GROUP */ 87433 , `formControlName cannot be used with an ngModelGroup parent. It is only compatible with parents 87434 that also have a "form" prefix: formGroupName, formArrayName, or formGroup. 87435 87436 Option 1: Update the parent to be formGroupName (reactive form strategy) 87437 87438 ${formGroupNameExample} 87439 87440 Option 2: Use ngModel instead of formControlName (template-driven strategy) 87441 87442 ${ngModelGroupExample}`); 87443} 87444 87445function missingFormException() { 87446 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1052 87447 /* RuntimeErrorCode.FORM_GROUP_MISSING_INSTANCE */ 87448 , `formGroup expects a FormGroup instance. Please pass one in. 87449 87450 Example: 87451 87452 ${formControlNameExample}`); 87453} 87454 87455function groupParentException() { 87456 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1053 87457 /* RuntimeErrorCode.FORM_GROUP_NAME_MISSING_PARENT */ 87458 , `formGroupName must be used with a parent formGroup directive. You'll want to add a formGroup 87459 directive and pass it an existing FormGroup instance (you can create one in your class). 87460 87461 Example: 87462 87463 ${formGroupNameExample}`); 87464} 87465 87466function arrayParentException() { 87467 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1054 87468 /* RuntimeErrorCode.FORM_ARRAY_NAME_MISSING_PARENT */ 87469 , `formArrayName must be used with a parent formGroup directive. You'll want to add a formGroup 87470 directive and pass it an existing FormGroup instance (you can create one in your class). 87471 87472 Example: 87473 87474 ${formArrayNameExample}`); 87475} 87476 87477const disabledAttrWarning = ` 87478 It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true 87479 when you set up this control in your component class, the disabled attribute will actually be set in the DOM for 87480 you. We recommend using this approach to avoid 'changed after checked' errors. 87481 87482 Example: 87483 // Specify the \`disabled\` property at control creation time: 87484 form = new FormGroup({ 87485 first: new FormControl({value: 'Nancy', disabled: true}, Validators.required), 87486 last: new FormControl('Drew', Validators.required) 87487 }); 87488 87489 // Controls can also be enabled/disabled after creation: 87490 form.get('first')?.enable(); 87491 form.get('last')?.disable(); 87492`; 87493const asyncValidatorsDroppedWithOptsWarning = ` 87494 It looks like you're constructing using a FormControl with both an options argument and an 87495 async validators argument. Mixing these arguments will cause your async validators to be dropped. 87496 You should either put all your validators in the options object, or in separate validators 87497 arguments. For example: 87498 87499 // Using validators arguments 87500 fc = new FormControl(42, Validators.required, myAsyncValidator); 87501 87502 // Using AbstractControlOptions 87503 fc = new FormControl(42, {validators: Validators.required, asyncValidators: myAV}); 87504 87505 // Do NOT mix them: async validators will be dropped! 87506 fc = new FormControl(42, {validators: Validators.required}, /* Oops! */ myAsyncValidator); 87507`; 87508 87509function ngModelWarning(directiveName) { 87510 return ` 87511 It looks like you're using ngModel on the same form field as ${directiveName}. 87512 Support for using the ngModel input property and ngModelChange event with
87513 reactive form directives has been deprecated in Angular v6 and will be removed 87514 in a future version of Angular. 87515 87516 For more information on this, see our API docs here: 87517 https://angular.io/api/forms/${directiveName === 'formControl' ? 'FormControlDirective' : 'FormControlName'}#use-with-ngmodel 87518 `; 87519} 87520 87521function describeKey(isFormGroup, key) { 87522 return isFormGroup ? `with name: '${key}'` : `at index: ${key}`; 87523} 87524 87525function noControlsError(isFormGroup) { 87526 return ` 87527 There are no form controls registered with this ${isFormGroup ? 'group' : 'array'} yet. If you're using ngModel, 87528 you may want to check next tick (e.g. use setTimeout). 87529 `; 87530} 87531 87532function missingControlError(isFormGroup, key) { 87533 return `Cannot find form control ${describeKey(isFormGroup, key)}`; 87534} 87535 87536function missingControlValueError(isFormGroup, key) { 87537 return `Must supply a value for form control ${describeKey(isFormGroup, key)}`; 87538} 87539/** 87540 * @license 87541 * Copyright Google LLC All Rights Reserved. 87542 * 87543 * Use of this source code is governed by an MIT-style license that can be 87544 * found in the LICENSE file at https://angular.io/license 87545 */ 87546 87547 87548const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode; 87549/** 87550 * Reports that a control is valid, meaning that no errors exist in the input value. 87551 * 87552 * @see `status` 87553 */ 87554 87555const VALID = 'VALID'; 87556/** 87557 * Reports that a control is invalid, meaning that an error exists in the input value. 87558 * 87559 * @see `status` 87560 */ 87561 87562const INVALID = 'INVALID'; 87563/** 87564 * Reports that a control is pending, meaning that that async validation is occurring and 87565 * errors are not yet available for the input value. 87566 * 87567 * @see `markAsPending` 87568 * @see `status` 87569 */ 87570 87571const PENDING = 'PENDING'; 87572/** 87573 * Reports that a control is disabled, meaning that the control is exempt from ancestor 87574 * calculations of validity or value. 87575 * 87576 * @see `markAsDisabled` 87577 * @see `status` 87578 */ 87579 87580const DISABLED = 'DISABLED'; 87581/** 87582 * Gets validators from either an options object or given validators. 87583 */ 87584 87585function pickValidators(validatorOrOpts) { 87586 return (isOptionsObj(validatorOrOpts) ? validatorOrOpts.validators : validatorOrOpts) || null; 87587} 87588/** 87589 * Creates validator function by combining provided validators. 87590 */ 87591 87592 87593function coerceToValidator(validator) { 87594 return Array.isArray(validator) ? composeValidators(validator) : validator || null; 87595} 87596/** 87597 * Gets async validators from either an options object or given validators. 87598 */ 87599 87600 87601function pickAsyncValidators(asyncValidator, validatorOrOpts) { 87602 if (typeof ngDevMode === 'undefined' || ngDevMode) { 87603 if (isOptionsObj(validatorOrOpts) && asyncValidator) { 87604 console.warn(asyncValidatorsDroppedWithOptsWarning); 87605 } 87606 } 87607 87608 return (isOptionsObj(validatorOrOpts) ? validatorOrOpts.asyncValidators : asyncValidator) || null; 87609} 87610/** 87611 * Creates async validator function by combining provided async validators. 87612 */ 87613 87614 87615function coerceToAsyncValidator(asyncValidator) { 87616 return Array.isArray(asyncValidator) ? composeAsyncValidators(asyncValidator) : asyncValidator || null; 87617} 87618 87619function isOptionsObj(validatorOrOpts) { 87620 return validatorOrOpts != null && !Array.isArray(validatorOrOpts) && typeof validatorOrOpts === 'object'; 87621} 87622 87623function assertControlPresent(parent, isGroup, key) { 87624 const controls = parent.controls; 87625 const collection = isGroup ? Object.keys(controls) : controls; 87626 87627 if (!collection.length) { 87628 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1000 87629 /* RuntimeErrorCode.NO_CONTROLS */ 87630 , NG_DEV_MODE ? noControlsError(isGroup) : ''); 87631 } 87632 87633 if (!controls[key]) { 87634 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1001 87635 /* RuntimeErrorCode.MISSING_CONTROL */ 87636 , NG_DEV_MODE ? missingControlError(isGroup, key) : ''); 87637 } 87638} 87639 87640function assertAllValuesPresent(control, isGroup, value) { 87641 control._forEachChild((_, key) => { 87642 if (value[key] === undefined) { 87643 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1002 87644 /* RuntimeErrorCode.MISSING_CONTROL_VALUE */ 87645 , NG_DEV_MODE ? missingControlValueError(isGroup, key) : ''); 87646 } 87647 }); 87648} // clang-format on 87649 87650/** 87651 * This is the base class for `FormControl`, `FormGroup`, and `FormArray`. 87652 *
87653 * It provides some of the shared behavior that all controls and groups of controls have, like 87654 * running validators, calculating status, and resetting state. It also defines the properties 87655 * that are shared between all sub-classes, like `value`, `valid`, and `dirty`. It shouldn't be 87656 * instantiated directly. 87657 * 87658 * The first type parameter TValue represents the value type of the control (`control.value`). 87659 * The optional type parameter TRawValue represents the raw value type (`control.getRawValue()`). 87660 * 87661 * @see [Forms Guide](/guide/forms) 87662 * @see [Reactive Forms Guide](/guide/reactive-forms) 87663 * @see [Dynamic Forms Guide](/guide/dynamic-form) 87664 * 87665 * @publicApi 87666 */ 87667 87668 87669class AbstractControl { 87670 /** 87671 * Initialize the AbstractControl instance. 87672 * 87673 * @param validators The function or array of functions that is used to determine the validity of 87674 * this control synchronously. 87675 * @param asyncValidators The function or array of functions that is used to determine validity of 87676 * this control asynchronously. 87677 */ 87678 constructor(validators, asyncValidators) { 87679 /** @internal */ 87680 this._pendingDirty = false; 87681 /** 87682 * Indicates that a control has its own pending asynchronous validation in progress. 87683 * 87684 * @internal 87685 */ 87686 87687 this._hasOwnPendingAsyncValidator = false; 87688 /** @internal */ 87689 87690 this._pendingTouched = false; 87691 /** @internal */ 87692 87693 this._onCollectionChange = () => {}; 87694 87695 this._parent = null; 87696 /** 87697 * A control is `pristine` if the user has not yet changed 87698 * the value in the UI. 87699 * 87700 * @returns True if the user has not yet changed the value in the UI; compare `dirty`. 87701 * Programmatic changes to a control's value do not mark it dirty. 87702 */ 87703 87704 this.pristine = true; 87705 /** 87706 * True if the control is marked as `touched`. 87707 * 87708 * A control is marked `touched` once the user has triggered 87709 * a `blur` event on it. 87710 */ 87711 87712 this.touched = false; 87713 /** @internal */ 87714 87715 this._onDisabledChange = []; 87716 this._rawValidators = validators; 87717 this._rawAsyncValidators = asyncValidators; 87718 this._composedValidatorFn = coerceToValidator(this._rawValidators); 87719 this._composedAsyncValidatorFn = coerceToAsyncValidator(this._rawAsyncValidators); 87720 } 87721 /** 87722 * Returns the function that is used to determine the validity of this control synchronously. 87723 * If multiple validators have been added, this will be a single composed function. 87724 * See `Validators.compose()` for additional information. 87725 */ 87726 87727 87728 get validator() { 87729 return this._composedValidatorFn; 87730 } 87731 87732 set validator(validatorFn) { 87733 this._rawValidators = this._composedValidatorFn = validatorFn; 87734 } 87735 /** 87736 * Returns the function that is used to determine the validity of this control asynchronously. 87737 * If multiple validators have been added, this will be a single composed function. 87738 * See `Validators.compose()` for additional information. 87739 */ 87740 87741 87742 get asyncValidator() { 87743 return this._composedAsyncValidatorFn; 87744 } 87745 87746 set asyncValidator(asyncValidatorFn) { 87747 this._rawAsyncValidators = this._composedAsyncValidatorFn = asyncValidatorFn; 87748 } 87749 /** 87750 * The parent control. 87751 */ 87752 87753 87754 get parent() { 87755 return this._parent; 87756 } 87757 /** 87758 * A control is `valid` when its `status` is `VALID`. 87759 * 87760 * @see {@link AbstractControl.status} 87761 * 87762 * @returns True if the control has passed all of its validation tests, 87763 * false otherwise. 87764 */ 87765 87766 87767 get valid() { 87768 return this.status === VALID; 87769 } 87770 /** 87771 * A control is `invalid` when its `status` is `INVALID`. 87772 * 87773 * @see {@link AbstractControl.status} 87774 * 87775 * @returns True if this control has failed one or more of its validation checks, 87776 * false otherwise. 87777 */ 87778 87779 87780 get invalid() { 87781 return this.status === INVALID; 87782 } 87783 /** 87784 * A control is `pending` when its `status` is `PENDING`. 87785 * 87786 * @see {@link AbstractControl.status} 87787 * 87788 * @returns True if this control is in the process of conducting a validation check, 87789 * false otherwise. 87790 */ 87791 87792 87793 get pending() { 87794 return this.status == PENDING; 87795 } 87796 /** 87797 * A control is `disabled` when its `status` is `DISABLED`. 87798 * 87799 * Disabled controls are exempt from validation checks and 87800 * are not included in the aggregate value of their ancestor 87801 * controls. 87802 * 87803 * @see {@link AbstractControl.status} 87804 * 87805 * @returns True if the control is disabled, false otherwise. 87806 */ 87807 87808 87809 get disabled() { 87810 return this.status === DISABLED; 87811 } 87812 /** 87813 * A control is `enabled` as long as its `status` is not `DISABLED`. 87814 * 87815 * @returns True if the control has any status other than 'DISABLED', 87816 * false if the status is 'DISABLED'. 87817 * 87818 * @see {@link AbstractControl.status} 87819 * 87820 */ 87821 87822 87823 get enabled() { 87824 return this.status !== DISABLED; 87825 } 87826 /** 87827 * A control is `dirty` if the user has changed the value 87828 * in the UI. 87829 * 87830 * @returns True if the user has changed the value of this control in the UI; compare `pristine`. 87831 * Programmatic changes to a control's value do not mark it dirty. 87832 */ 87833 87834 87835 get dirty() { 87836 return !this.pristine; 87837 } 87838 /** 87839 * True if the control has not been marked as touched 87840 * 87841 * A control is `untouched` if the user has not yet triggered 87842 * a `blur` event on it. 87843 */ 87844 87845 87846 get untouched() { 87847 return !this.touched; 87848 } 87849 /** 87850 * Reports the update strategy of the `AbstractControl` (meaning 87851 * the event on which the control updates itself). 87852 * Possible values: `'change'` | `'blur'` | `'submit'` 87853 * Default value: `'change'` 87854 */ 87855 87856 87857 get updateOn() { 87858 return this._updateOn ? this._updateOn : this.parent ? this.parent.updateOn : 'change'; 87859 } 87860 /** 87861 * Sets the synchronous validators that are active on this control. Calling 87862 * this overwrites any existing synchronous validators. 87863 * 87864 * When you add or remove a validator at run time, you must call
87865 * `updateValueAndValidity()` for the new validation to take effect. 87866 * 87867 * If you want to add a new validator without affecting existing ones, consider 87868 * using `addValidators()` method instead. 87869 */ 87870 87871 87872 setValidators(validators) { 87873 this._rawValidators = validators; 87874 this._composedValidatorFn = coerceToValidator(validators); 87875 } 87876 /** 87877 * Sets the asynchronous validators that are active on this control. Calling this 87878 * overwrites any existing asynchronous validators. 87879 * 87880 * When you add or remove a validator at run time, you must call 87881 * `updateValueAndValidity()` for the new validation to take effect. 87882 * 87883 * If you want to add a new validator without affecting existing ones, consider 87884 * using `addAsyncValidators()` method instead. 87885 */ 87886 87887 87888 setAsyncValidators(validators) { 87889 this._rawAsyncValidators = validators; 87890 this._composedAsyncValidatorFn = coerceToAsyncValidator(validators); 87891 } 87892 /** 87893 * Add a synchronous validator or validators to this control, without affecting other validators. 87894 * 87895 * When you add or remove a validator at run time, you must call 87896 * `updateValueAndValidity()` for the new validation to take effect. 87897 * 87898 * Adding a validator that already exists will have no effect. If duplicate validator functions 87899 * are present in the `validators` array, only the first instance would be added to a form 87900 * control. 87901 * 87902 * @param validators The new validator function or functions to add to this control. 87903 */ 87904 87905 87906 addValidators(validators) { 87907 this.setValidators(addValidators(validators, this._rawValidators)); 87908 } 87909 /** 87910 * Add an asynchronous validator or validators to this control, without affecting other 87911 * validators. 87912 * 87913 * When you add or remove a validator at run time, you must call 87914 * `updateValueAndValidity()` for the new validation to take effect. 87915 * 87916 * Adding a validator that already exists will have no effect. 87917 * 87918 * @param validators The new asynchronous validator function or functions to add to this control. 87919 */ 87920 87921 87922 addAsyncValidators(validators) { 87923 this.setAsyncValidators(addValidators(validators, this._rawAsyncValidators)); 87924 } 87925 /** 87926 * Remove a synchronous validator from this control, without affecting other validators. 87927 * Validators are compared by function reference; you must pass a reference to the exact same 87928 * validator function as the one that was originally set. If a provided validator is not found, 87929 * it is ignored. 87930 * 87931 * @usageNotes 87932 * 87933 * ### Reference to a ValidatorFn 87934 * 87935 * ``` 87936 * // Reference to the RequiredValidator 87937 * const ctrl = new FormControl<string | null>('', Validators.required); 87938 * ctrl.removeValidators(Validators.required); 87939 * 87940 * // Reference to anonymous function inside MinValidator 87941 * const minValidator = Validators.min(3); 87942 * const ctrl = new FormControl<string | null>('', minValidator); 87943 * expect(ctrl.hasValidator(minValidator)).toEqual(true) 87944 * expect(ctrl.hasValidator(Validators.min(3)).toEqual(false) 87945 * 87946 * ctrl.removeValidators(minValidator); 87947 * ``` 87948 * 87949 * When you add or remove a validator at run time, you must call 87950 * `updateValueAndValidity()` for the new validation to take effect. 87951 * 87952 * @param validators The validator or validators to remove. 87953 */ 87954 87955 87956 removeValidators(validators) { 87957 this.setValidators(removeValidators(validators, this._rawValidators)); 87958 } 87959 /** 87960 * Remove an asynchronous validator from this control, without affecting other validators. 87961 * Validators are compared by function reference; you must pass a reference to the exact same 87962 * validator function as the one that was originally set. If a provided validator is not found, it 87963 * is ignored. 87964 * 87965 * When you add or remove a validator at run time, you must call 87966 * `updateValueAndValidity()` for the new validation to take effect. 87967 * 87968 * @param validators The asynchronous validator or validators to remove. 87969 */ 87970 87971 87972 removeAsyncValidators(validators) { 87973 this.setAsyncValidators(removeValidators(validators, this._rawAsyncValidators)); 87974 } 87975 /** 87976 * Check whether a synchronous validator function is present on this control. The provided 87977 * validator must be a reference to the exact same function that was provided. 87978 * 87979 * @usageNotes 87980 * 87981 * ### Reference to a ValidatorFn 87982 * 87983 * ``` 87984 * // Reference to the RequiredValidator 87985 * const ctrl = new FormControl<number | null>(0, Validators.required); 87986 * expect(ctrl.hasValidator(Validators.required)).toEqual(true) 87987 * 87988 * // Reference to anonymous function inside MinValidator 87989 * const minValidator = Validators.min(3); 87990 * const ctrl = new FormControl<number | null>(0, minValidator); 87991 * expect(ctrl.hasValidator(minValidator)).toEqual(true) 87992 * expect(ctrl.hasValidator(Validators.min(3)).toEqual(false) 87993 * ``` 87994 * 87995 * @param validator The validator to check for presence. Compared by function reference. 87996 * @returns Whether the provided validator was found on this control. 87997 */ 87998 87999 88000 hasValidator(validator) { 88001 return hasValidator(this._rawValidators, validator); 88002 } 88003 /** 88004 * Check whether an asynchronous validator function is present on this control. The provided 88005 * validator must be a reference to the exact same function that was provided. 88006 * 88007 * @param validator The asynchronous validator to check for presence. Compared by function 88008 * reference. 88009 * @returns Whether the provided asynchronous validator was found on this control. 88010 */ 88011 88012 88013 hasAsyncValidator(validator) { 88014 return hasValidator(this._rawAsyncValidators, validator); 88015 } 88016 /** 88017 * Empties out the synchronous validator list. 88018 * 88019 * When you add or remove a validator at run time, you must call
88020 * `updateValueAndValidity()` for the new validation to take effect. 88021 * 88022 */ 88023 88024 88025 clearValidators() { 88026 this.validator = null; 88027 } 88028 /** 88029 * Empties out the async validator list. 88030 * 88031 * When you add or remove a validator at run time, you must call 88032 * `updateValueAndValidity()` for the new validation to take effect. 88033 * 88034 */ 88035 88036 88037 clearAsyncValidators() { 88038 this.asyncValidator = null; 88039 } 88040 /** 88041 * Marks the control as `touched`. A control is touched by focus and 88042 * blur events that do not change the value. 88043 * 88044 * @see `markAsUntouched()` 88045 * @see `markAsDirty()` 88046 * @see `markAsPristine()` 88047 * 88048 * @param opts Configuration options that determine how the control propagates changes 88049 * and emits events after marking is applied. 88050 * * `onlySelf`: When true, mark only this control. When false or not supplied, 88051 * marks all direct ancestors. Default is false. 88052 */ 88053 88054 88055 markAsTouched(opts = {}) { 88056 this.touched = true; 88057 88058 if (this._parent && !opts.onlySelf) { 88059 this._parent.markAsTouched(opts); 88060 } 88061 } 88062 /**
88063 * Marks the control and all its descendant controls as `touched`. 88064 * @see `markAsTouched()` 88065 */ 88066 88067 88068 markAllAsTouched() { 88069 this.markAsTouched({ 88070 onlySelf: true 88071 }); 88072 88073 this._forEachChild(control => control.markAllAsTouched()); 88074 } 88075 /** 88076 * Marks the control as `untouched`. 88077 * 88078 * If the control has any children, also marks all children as `untouched` 88079 * and recalculates the `touched` status of all parent controls. 88080 * 88081 * @see `markAsTouched()` 88082 * @see `markAsDirty()` 88083 * @see `markAsPristine()` 88084 * 88085 * @param opts Configuration options that determine how the control propagates changes 88086 * and emits events after the marking is applied. 88087 * * `onlySelf`: When true, mark only this control. When false or not supplied, 88088 * marks all direct ancestors. Default is false. 88089 */ 88090 88091 88092 markAsUntouched(opts = {}) { 88093 this.touched = false; 88094 this._pendingTouched = false; 88095 88096 this._forEachChild(control => { 88097 control.markAsUntouched({ 88098 onlySelf: true 88099 }); 88100 }); 88101 88102 if (this._parent && !opts.onlySelf) { 88103 this._parent._updateTouched(opts); 88104 } 88105 } 88106 /** 88107 * Marks the control as `dirty`. A control becomes dirty when 88108 * the control's value is changed through the UI; compare `markAsTouched`. 88109 * 88110 * @see `markAsTouched()` 88111 * @see `markAsUntouched()` 88112 * @see `markAsPristine()` 88113 * 88114 * @param opts Configuration options that determine how the control propagates changes 88115 * and emits events after marking is applied. 88116 * * `onlySelf`: When true, mark only this control. When false or not supplied, 88117 * marks all direct ancestors. Default is false. 88118 */ 88119 88120 88121 markAsDirty(opts = {}) { 88122 this.pristine = false; 88123 88124 if (this._parent && !opts.onlySelf) { 88125 this._parent.markAsDirty(opts); 88126 } 88127 } 88128 /** 88129 * Marks the control as `pristine`. 88130 * 88131 * If the control has any children, marks all children as `pristine`, 88132 * and recalculates the `pristine` status of all parent 88133 * controls. 88134 * 88135 * @see `markAsTouched()` 88136 * @see `markAsUntouched()` 88137 * @see `markAsDirty()` 88138 * 88139 * @param opts Configuration options that determine how the control emits events after 88140 * marking is applied. 88141 * * `onlySelf`: When true, mark only this control. When false or not supplied, 88142 * marks all direct ancestors. Default is false. 88143 */ 88144 88145 88146 markAsPristine(opts = {}) { 88147 this.pristine = true; 88148 this._pendingDirty = false; 88149 88150 this._forEachChild(control => { 88151 control.markAsPristine({ 88152 onlySelf: true 88153 }); 88154 }); 88155 88156 if (this._parent && !opts.onlySelf) { 88157 this._parent._updatePristine(opts); 88158 } 88159 } 88160 /** 88161 * Marks the control as `pending`. 88162 * 88163 * A control is pending while the control performs async validation. 88164 * 88165 * @see {@link AbstractControl.status} 88166 * 88167 * @param opts Configuration options that determine how the control propagates changes and 88168 * emits events after marking is applied. 88169 * * `onlySelf`: When true, mark only this control. When false or not supplied, 88170 * marks all direct ancestors. Default is false. 88171 * * `emitEvent`: When true or not supplied (the default), the `statusChanges` 88172 * observable emits an event with the latest status the control is marked pending. 88173 * When false, no events are emitted. 88174 * 88175 */ 88176 88177 88178 markAsPending(opts = {}) { 88179 this.status = PENDING; 88180 88181 if (opts.emitEvent !== false) { 88182 this.statusChanges.emit(this.status); 88183 } 88184 88185 if (this._parent && !opts.onlySelf) { 88186 this._parent.markAsPending(opts); 88187 } 88188 } 88189 /** 88190 * Disables the control. This means the control is exempt from validation checks and 88191 * excluded from the aggregate value of any parent. Its status is `DISABLED`. 88192 * 88193 * If the control has children, all children are also disabled. 88194 * 88195 * @see {@link AbstractControl.status} 88196 * 88197 * @param opts Configuration options that determine how the control propagates 88198 * changes and emits events after the control is disabled. 88199 * * `onlySelf`: When true, mark only this control. When false or not supplied, 88200 * marks all direct ancestors. Default is false. 88201 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 88202 * `valueChanges` 88203 * observables emit events with the latest status and value when the control is disabled. 88204 * When false, no events are emitted. 88205 */ 88206 88207 88208 disable(opts = {}) { 88209 // If parent has been marked artificially dirty we don't want to re-calculate the 88210 // parent's dirtiness based on the children.
88211 const skipPristineCheck = this._parentMarkedDirty(opts.onlySelf); 88212 88213 this.status = DISABLED; 88214 this.errors = null; 88215 88216 this._forEachChild(control => { 88217 control.disable({ ...opts, 88218 onlySelf: true 88219 }); 88220 }); 88221 88222 this._updateValue(); 88223 88224 if (opts.emitEvent !== false) { 88225 this.valueChanges.emit(this.value); 88226 this.statusChanges.emit(this.status); 88227 } 88228 88229 this._updateAncestors({ ...opts, 88230 skipPristineCheck 88231 }); 88232 88233 this._onDisabledChange.forEach(changeFn => changeFn(true)); 88234 } 88235 /** 88236 * Enables the control. This means the control is included in validation checks and 88237 * the aggregate value of its parent. Its status recalculates based on its value and 88238 * its validators. 88239 * 88240 * By default, if the control has children, all children are enabled. 88241 * 88242 * @see {@link AbstractControl.status} 88243 * 88244 * @param opts Configure options that control how the control propagates changes and 88245 * emits events when marked as untouched 88246 * * `onlySelf`: When true, mark only this control. When false or not supplied, 88247 * marks all direct ancestors. Default is false. 88248 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 88249 * `valueChanges` 88250 * observables emit events with the latest status and value when the control is enabled. 88251 * When false, no events are emitted. 88252 */ 88253 88254 88255 enable(opts = {}) { 88256 // If parent has been marked artificially dirty we don't want to re-calculate the 88257 // parent's dirtiness based on the children. 88258 const skipPristineCheck = this._parentMarkedDirty(opts.onlySelf); 88259 88260 this.status = VALID; 88261 88262 this._forEachChild(control => { 88263 control.enable({ ...opts, 88264 onlySelf: true 88265 }); 88266 }); 88267 88268 this.updateValueAndValidity({ 88269 onlySelf: true, 88270 emitEvent: opts.emitEvent 88271 }); 88272 88273 this._updateAncestors({ ...opts, 88274 skipPristineCheck 88275 }); 88276 88277 this._onDisabledChange.forEach(changeFn => changeFn(false)); 88278 } 88279 88280 _updateAncestors(opts) { 88281 if (this._parent && !opts.onlySelf) { 88282 this._parent.updateValueAndValidity(opts); 88283 88284 if (!opts.skipPristineCheck) { 88285 this._parent._updatePristine(); 88286 } 88287 88288 this._parent._updateTouched(); 88289 } 88290 } 88291 /** 88292 * Sets the parent of the control 88293 * 88294 * @param parent The new parent. 88295 */ 88296 88297 88298 setParent(parent) { 88299 this._parent = parent; 88300 } 88301 /** 88302 * The raw value of this control. For most control implementations, the raw value will include 88303 * disabled children. 88304 */ 88305 88306 88307 getRawValue() { 88308 return this.value; 88309 } 88310 /** 88311 * Recalculates the value and validation status of the control. 88312 * 88313 * By default, it also updates the value and validity of its ancestors. 88314 * 88315 * @param opts Configuration options determine how the control propagates changes and emits events 88316 * after updates and validity checks are applied. 88317 * * `onlySelf`: When true, only update this control. When false or not supplied, 88318 * update all direct ancestors. Default is false. 88319 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 88320 * `valueChanges` 88321 * observables emit events with the latest status and value when the control is updated. 88322 * When false, no events are emitted. 88323 */ 88324 88325 88326 updateValueAndValidity(opts = {}) { 88327 this._setInitialStatus(); 88328 88329 this._updateValue(); 88330 88331 if (this.enabled) { 88332 this._cancelExistingSubscription(); 88333 88334 this.errors = this._runValidator(); 88335 this.status = this._calculateStatus(); 88336 88337 if (this.status === VALID || this.status === PENDING) { 88338 this._runAsyncValidator(opts.emitEvent); 88339 } 88340 } 88341 88342 if (opts.emitEvent !== false) { 88343 this.valueChanges.emit(this.value); 88344 this.statusChanges.emit(this.status); 88345 } 88346 88347 if (this._parent && !opts.onlySelf) { 88348 this._parent.updateValueAndValidity(opts); 88349 } 88350 } 88351 /** @internal */ 88352 88353 88354 _updateTreeValidity(opts = { 88355 emitEvent: true 88356 }) { 88357 this._forEachChild(ctrl => ctrl._updateTreeValidity(opts)); 88358 88359 this.updateValueAndValidity({ 88360 onlySelf: true, 88361 emitEvent: opts.emitEvent 88362 }); 88363 } 88364 88365 _setInitialStatus() { 88366 this.status = this._allControlsDisabled() ? DISABLED : VALID; 88367 } 88368 88369 _runValidator() { 88370 return this.validator ? this.validator(this) : null; 88371 } 88372 88373 _runAsyncValidator(emitEvent) { 88374 if (this.asyncValidator) { 88375 this.status = PENDING; 88376 this._hasOwnPendingAsyncValidator = true; 88377 const obs = toObservable(this.asyncValidator(this)); 88378 this._asyncValidationSubscription = obs.subscribe(errors => { 88379 this._hasOwnPendingAsyncValidator = false; // This will trigger the recalculation of the validation status, which depen
88379ds on 88380 // the state of the asynchronous validation (whether it is in progress or not). So, it is 88381 // necessary that we have updated the `_hasOwnPendingAsyncValidator` boolean flag first. 88382 88383 this.setErrors(errors, { 88384 emitEvent 88385 }); 88386 }); 88387 } 88388 } 88389 88390 _cancelExistingSubscription() { 88391 if (this._asyncValidationSubscription) { 88392 this._asyncValidationSubscription.unsubscribe(); 88393 88394 this._hasOwnPendingAsyncValidator = false; 88395 } 88396 } 88397 /** 88398 * Sets errors on a form control when running validations manually, rather than automatically. 88399 * 88400 * Calling `setErrors` also updates the validity of the parent control. 88401 * 88402 * @param opts Configuration options that determine how the control propagates 88403 * changes and emits events after the control errors are set. 88404 * * `emitEvent`: When true or not supplied (the default), the `statusChanges` 88405 * observable emits an event after the errors are set. 88406 * 88407 * @usageNotes 88408 * 88409 * ### Manually set the errors for a control 88410 * 88411 * ``` 88412 * const login = new FormControl('someLogin'); 88413 * login.setErrors({ 88414 * notUnique: true 88415 * }); 88416 * 88417 * expect(login.valid).toEqual(false); 88418 * expect(login.errors).toEqual({ notUnique: true }); 88419 * 88420 * login.setValue('someOtherLogin'); 88421 * 88422 * expect(login.valid).toEqual(true); 88423 * ``` 88424 */ 88425 88426 88427 setErrors(errors, opts = {}) { 88428 this.errors = errors; 88429 88430 this._updateControlsErrors(opts.emitEvent !== false); 88431 } 88432 /** 88433 * Retrieves a child control given the control's name or path. 88434 * 88435 * @param path A dot-delimited string or array of string/number values that define the path to the 88436 * control. If a string is provided, passing it as a string literal will result in improved type 88437 * information. Likewise, if an array is provided, passing it `as const` will cause improved type 88438 * information to be available. 88439 * 88440 * @usageNotes 88441 * ### Retrieve a nested control 88442 * 88443 * For example, to get a `name` control nested within a `person` sub-group: 88444 * 88445 * * `this.form.get('person.name');` 88446 * 88447 * -OR- 88448 * 88449 * * `this.form.get(['person', 'name'] as const);` // `as const` gives improved typings 88450 * 88451 * ### Retrieve a control in a FormArray 88452 * 88453 * When accessing an element inside a FormArray, you can use an element index. 88454 * For example, to get a `price` control from the first element in an `items` array you can use: 88455 * 88456 * * `this.form.get('items.0.price');` 88457 * 88458 * -OR- 88459 * 88460 * * `this.form.get(['items', 0, 'price']);` 88461 */ 88462 88463 88464 get(path) {
vendor: 5,312 bytes, lines 88465-88666
88465 let currPath = path; 88466 if (currPath == null) return null; 88467 if (!Array.isArray(currPath)) currPath = currPath.split('.'); 88468 if (currPath.length === 0) return null; 88469 return currPath.reduce((control, name) => control && control._find(name), this); 88470 } 88471 /** 88472 * @description 88473 * Reports error data for the control with the given path. 88474 * 88475 * @param errorCode The code of the error to check 88476 * @param path A list of control names that designates how to move from the current control 88477 * to the control that should be queried for errors. 88478 * 88479 * @usageNotes 88480 * For example, for the following `FormGroup`: 88481 * 88482 * ``` 88483 * form = new FormGroup({ 88484 * address: new FormGroup({ street: new FormControl() }) 88485 * }); 88486 * ``` 88487 * 88488 * The path to the 'street' control from the root form would be 'address' -> 'street'. 88489 * 88490 * It can be provided to this method in one of two formats: 88491 * 88492 * 1. An array of string control names, e.g. `['address', 'street']` 88493 * 1. A period-delimited list of control names in one string, e.g. `'address.street'` 88494 * 88495 * @returns error data for that particular error. If the control or error is not present, 88496 * null is returned. 88497 */ 88498 88499 88500 getError(errorCode, path) { 88501 const control = path ? this.get(path) : this; 88502 return control && control.errors ? control.errors[errorCode] : null; 88503 } 88504 /** 88505 * @description 88506 * Reports whether the control with the given path has the error specified. 88507 * 88508 * @param errorCode The code of the error to check 88509 * @param path A list of control names that designates how to move from the current control 88510 * to the control that should be queried for errors. 88511 * 88512 * @usageNotes 88513 * For example, for the following `FormGroup`: 88514 * 88515 * ``` 88516 * form = new FormGroup({ 88517 * address: new FormGroup({ street: new FormControl() }) 88518 * }); 88519 * ``` 88520 * 88521 * The path to the 'street' control from the root form would be 'address' -> 'street'. 88522 * 88523 * It can be provided to this method in one of two formats: 88524 * 88525 * 1. An array of string control names, e.g. `['address', 'street']` 88526 * 1. A period-delimited list of control names in one string, e.g. `'address.street'` 88527 * 88528 * If no path is given, this method checks for the error on the current control. 88529 * 88530 * @returns whether the given error is present in the control at the given path. 88531 * 88532 * If the control is not present, false is returned. 88533 */ 88534 88535 88536 hasError(errorCode, path) { 88537 return !!this.getError(errorCode, path); 88538 } 88539 /** 88540 * Retrieves the top-level ancestor of this control. 88541 */ 88542 88543 88544 get root() { 88545 let x = this; 88546 88547 while (x._parent) { 88548 x = x._parent; 88549 } 88550 88551 return x; 88552 } 88553 /** @internal */ 88554 88555 88556 _updateControlsErrors(emitEvent) { 88557 this.status = this._calculateStatus(); 88558 88559 if (emitEvent) { 88560 this.statusChanges.emit(this.status); 88561 } 88562 88563 if (this._parent) { 88564 this._parent._updateControlsErrors(emitEvent); 88565 } 88566 } 88567 /** @internal */ 88568 88569 88570 _initObservables() { 88571 this.valueChanges = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); 88572 this.statusChanges = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); 88573 } 88574 88575 _calculateStatus() { 88576 if (this._allControlsDisabled()) return DISABLED; 88577 if (this.errors) return INVALID; 88578 if (this._hasOwnPendingAsyncValidator || this._anyControlsHaveStatus(PENDING)) return PENDING; 88579 if (this._anyControlsHaveStatus(INVALID)) return INVALID; 88580 return VALID; 88581 } 88582 /** @internal */ 88583 88584 88585 _anyControlsHaveStatus(status) { 88586 return this._anyControls(control => control.status === status); 88587 } 88588 /** @internal */ 88589 88590 88591 _anyControlsDirty() { 88592 return this._anyControls(control => control.dirty); 88593 } 88594 /** @internal */ 88595 88596 88597 _anyControlsTouched() { 88598 return this._anyControls(control => control.touched); 88599 } 88600 /** @internal */ 88601 88602 88603 _updatePristine(opts = {}) { 88604 this.pristine = !this._anyControlsDirty(); 88605 88606 if (this._parent && !opts.onlySelf) { 88607 this._parent._updatePristine(opts); 88608 } 88609 } 88610 /** @internal */ 88611 88612 88613 _updateTouched(opts = {}) { 88614 this.touched = this._anyControlsTouched(); 88615 88616 if (this._parent && !opts.onlySelf) { 88617 this._parent._updateTouched(opts); 88618 } 88619 } 88620 /** @internal */ 88621 88622 88623 _registerOnCollectionChange(fn) { 88624 this._onCollectionChange = fn; 88625 } 88626 /** @internal */ 88627 88628 88629 _setUpdateStrategy(opts) { 88630 if (isOptionsObj(opts) && opts.updateOn != null) { 88631 this._updateOn = opts.updateOn; 88632 } 88633 } 88634 /** 88635 * Check to see if parent has been marked artificially dirty. 88636 * 88637 * @internal 88638 */ 88639 88640 88641 _parentMarkedDirty(onlySelf) { 88642 const parentDirty = this._parent && this._parent.dirty; 88643 return !onlySelf && !!parentDirty && !this._parent._anyControlsDirty(); 88644 } 88645 /** @internal */ 88646 88647 88648 _find(name) { 88649 return null; 88650 } 88651 88652} 88653/** 88654 * @license 88655 * Copyright Google LLC All Rights Reserved. 88656 * 88657 * Use of this source code is governed by an MIT-style license that can be 88658 * found in the LICENSE file at https://angular.io/license 88659 */ 88660 88661/** 88662 * Tracks the value and validity state of a group of `FormControl` instances. 88663 * 88664 * A `FormGroup` aggregates the values of each child `FormControl` into one object, 88665 * with each control name as the key. It calculates its status by reducing the status values 88666 * of its children. For example, if one of the controls in a group is invali
88666d, the entire 88667 * group becomes invalid. 88668 * 88669 * `FormGroup` is one of the four fundamental building blocks used to define forms in Angular, 88670 * along with `FormControl`, `FormArray`, and `FormRecord`. 88671 * 88672 * When instantiating a `FormGroup`, pass in a collection of child controls as the first 88673 * argument. The key for each child registers the name for the control. 88674 * 88675 * `FormGroup` is intended for use cases where the keys are known ahead of time. 88676 * If you need to dynamically add and remove controls, use {@link FormRecord} instead. 88677 * 88678 * `FormGroup` accepts an optional type parameter `TControl`, which is an object type with inner 88679 * control types as values. 88680 * 88681 * @usageNotes 88682 * 88683 * ### Create a form group with 2 controls 88684 * 88685 * ``` 88686 * const form = new FormGroup({ 88687 * first: new FormControl('Nancy', Validators.minLength(2)), 88688 * last: new FormControl('Drew'), 88689 * }); 88690 * 88691 * console.log(form.value); // {first: 'Nancy', last; 'Drew'} 88692 * console.log(form.status); // 'VALID' 88693 * ``` 88694 * 88695 * ### The type argument, and optional controls 88696 * 88697 * `FormGroup` accepts one generic argument, which is an object c
88697ontaining its inner controls. 88698 * This type will usually be inferred automatically, but you can always specify it explicitly if you 88699 * wish. 88700 * 88701 * If you have controls that are optional (i.e. they can be removed, you can use the `?` in the 88702 * type): 88703 * 88704 * ``` 88705 * const form = new FormGroup<{ 88706 * first: FormControl<string|null>, 88707 * middle?: FormControl<string|null>, // Middle name is optional. 88708 * last: FormControl<string|null>, 88709 * }>({ 88710 * first: new FormControl('Nancy'), 88711 * last: new FormControl('Drew'), 88712 * }); 88713 * ``` 88714 * 88715 * ### Create a form group with a group-level validator 88716 * 88717 * You include group-level validators as the second arg, or group-level async 88718 * validators as the third arg. These come in handy when you want to perform validation 88719 * that considers the value of more than one child control. 88720 * 88721 * ``` 88722 * const form = new FormGroup({ 88723 * password: new FormControl('', Validators.minLength(2)), 88724 * passwordConfirm: new FormControl('', Validators.minLength(2)), 88725 * }, passwordMatchValidator); 88726 * 88727 * 88728 * function passwordMatchValidator(g: FormGroup) { 88729 * return g.get('password').value === g.get('passwordConfirm').value 88730 * ? null : {'mismatch': true}; 88731 * } 88732 * ``` 88733 * 88734 * Like `FormControl` instances, you choose to pass in 88735 * validators and async validators as part of an options object. 88736 * 88737 * ``` 88738 * const form = new FormGroup({ 88739 * password: new FormControl('') 88740 * passwordConfirm: new FormControl('') 88741 * }, { validators: passwordMatchValidator, asyncValidators: otherValidator }); 88742 * ``` 88743 * 88744 * ### Set the updateOn property for all controls in a form group 88745 * 88746 * The options object is used to set a default value for each child 88747 * control's `updateOn` property. If you set `updateOn` to `'blur'` at the 88748 * group level, all child controls default to 'blur', unless the child 88749 * has explicitly specified a different `updateOn` value. 88750 * 88751 * ```ts 88752 * const c = new FormGroup({ 88753 * one: new FormControl() 88754 * }, { updateOn: 'blur' }); 88755 * ``` 88756 * 88757 * ### Using a FormGroup with optional controls 88758 * 88759 * It is possible to have optional controls in a FormGroup. An optional control can be removed later 88760 * using `removeControl`, and can be omitted when calling `reset`. Optional controls must be 88761 * declared optional in the group's type. 88762 * 88763 * ```ts 88764 * const c = new FormGroup<{one?: FormControl<string>}>({ 88765 * one: new FormControl('') 88766 * }); 88767 * ``` 88768 * 88769 * Notice that `c.value.one` has type `string|null|undefined`. This is because calling `c.reset({})` 88770 * without providing the optional key `one` will cause it to become `null`. 88771 * 88772 * @publicApi 88773 */ 88774 88775 88776class FormGroup extends AbstractControl { 88777 /** 88778 * Creates a new `FormGroup` instance. 88779 * 88780 * @param controls A collection of child controls. The key for each child is the name 88781 * under which it is registered. 88782 * 88783 * @param validatorOrOpts A synchronous validator function, or an array of 88784 * such functions, or an `AbstractControlOptions` object that contains validation functions 88785 * and a validation trigger. 88786 * 88787 * @param asyncValidator A single async validator or array of async validator functions 88788 * 88789 */ 88790 constructor(controls, validatorOrOpts, asyncValidator) { 88791 super(pickValidators(validatorOrOpts), pickAsyncValidators(asyncValidator, validatorOrOpts)); 88792 this.controls = controls; 88793 88794 this._initObservables(); 88795 88796 this._setUpdateStrategy(validatorOrOpts); 88797 88798 this._setUpControls(); 88799 88800 this.updateValueAndValidity({ 88801 onlySelf: true, 88802 // If `asyncValidator` is present, it will trigger control status change from `PENDING` to 88803 // `VALID` or `INVALID`. The status should be broadcasted via the `statusChanges` observable, 88804 // so we set `emitEvent` to `true` to allow that during the control creation process. 88805 emitEvent: !!this.asyncValidator 88806 }); 88807 } 88808 88809 registerControl(name, control) { 88810 if (this.controls[name]) return this.controls[name]; 88811 this.controls[name] = control; 88812 control.setParent(this); 88813 88814 control._registerOnCollectionChange(this._onCollectionChange); 88815 88816 return control; 88817 } 88818 88819 addControl(name, control, options = {}) { 88820 this.registerControl(name, control);
vendor: 26,860 bytes, lines 88821-89606
88821 this.updateValueAndValidity({ 88822 emitEvent: options.emitEvent 88823 }); 88824 88825 this._onCollectionChange(); 88826 } 88827 /** 88828 * Remove a control from this group. In a strongly-typed group, required controls cannot be 88829 * removed. 88830 * 88831 * This method also updates the value and validity of the control. 88832 * 88833 * @param name The control name to remove from the collection 88834 * @param options Specifies whether this FormGroup instance should emit events after a 88835 * control is removed. 88836 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 88837 * `valueChanges` observables emit events with the latest status and value when the control is 88838 * removed. When false, no events are emitted. 88839 */ 88840 88841 88842 removeControl(name, options = {}) { 88843 if (this.controls[name]) this.controls[name]._registerOnCollectionChange(() => {}); 88844 delete this.controls[name]; 88845 this.updateValueAndValidity({ 88846 emitEvent: options.emitEvent 88847 }); 88848 88849 this._onCollectionChange(); 88850 } 88851 88852 setControl(name, control, options = {}) { 88853 if (this.controls[name]) this.controls[name]._registerOnCollectionChange(() => {}); 88854 delete this.controls[name]; 88855 if (control) this.registerControl(name, control); 88856 this.updateValueAndValidity({ 88857 emitEvent: options.emitEvent 88858 }); 88859 88860 this._onCollectionChange(); 88861 } 88862 88863 contains(controlName) { 88864 return this.controls.hasOwnProperty(controlName) && this.controls[controlName].enabled; 88865 } 88866 /** 88867 * Sets the value of the `FormGroup`. It accepts an object that matches 88868 * the structure of the group, with control names as keys. 88869 * 88870 * @usageNotes 88871 * ### Set the complete value for the form group 88872 * 88873 * ``` 88874 * const form = new FormGroup({ 88875 * first: new FormControl(), 88876 * last: new FormControl() 88877 * }); 88878 * 88879 * console.log(form.value); // {first: null, last: null} 88880 * 88881 * form.setValue({first: 'Nancy', last: 'Drew'}); 88882 * console.log(form.value); // {first: 'Nancy', last: 'Drew'} 88883 * ``` 88884 * 88885 * @throws When strict checks fail, such as setting the value of a control 88886 * that doesn't exist or if you exclude a value of a control that does exist. 88887 * 88888 * @param value The new value for the control that matches the structure of the group. 88889 * @param options Configuration options that determine how the control propagates changes 88890 * and emits events after the value changes. 88891 * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity 88892 * updateValueAndValidity} method. 88893 * 88894 * * `onlySelf`: When true, each change only affects this control, and not its parent. Default is 88895 * false. 88896 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 88897 * `valueChanges` 88898 * observables emit events with the latest status and value when the control value is updated. 88899 * When false, no events are emitted. 88900 */ 88901 88902 88903 setValue(value, options = {}) { 88904 assertAllValuesPresent(this, true, value); 88905 Object.keys(value).forEach(name => { 88906 assertControlPresent(this, true, name); 88907 this.controls[name].setValue(value[name], { 88908 onlySelf: true, 88909 emitEvent: options.emitEvent 88910 }); 88911 }); 88912 this.updateValueAndValidity(options); 88913 } 88914 /** 88915 * Patches the value of the `FormGroup`. It accepts an object with control 88916 * names as keys, and does its best to match the values to the correct controls 88917 * in the group. 88918 * 88919 * It accepts both super-sets and sub-sets of the group without throwing an error. 88920 * 88921 * @usageNotes 88922 * ### Patch the value for a form group 88923 * 88924 * ``` 88925 * const form = new FormGroup({ 88926 * first: new FormControl(), 88927 * last: new FormControl() 88928 * }); 88929 * console.log(form.value); // {first: null, last: null} 88930 * 88931 * form.patchValue({first: 'Nancy'}); 88932 * console.log(form.value); // {first: 'Nancy', last: null} 88933 * ``` 88934 * 88935 * @param value The object that matches the structure of the group. 88936 * @param options Configuration options that determine how the control propagates changes and 88937 * emits events after the value is patched. 88938 * * `onlySelf`: When true, each change only affects this control and not its parent. Default is 88939 * true. 88940 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 88941 * `valueChanges` observables emit events with the latest status and value when the control value 88942 * is updated. When false, no events are emitted. The configuration options are passed to 88943 * the {@link AbstractControl#updateValueAndValidity updateValueAndValidity} method. 88944 */ 88945 88946 88947 patchValue(value, options = {}) { 88948 // Even though the `value` argument type doesn't allow `null` and `undefined` values, the 88949 // `patchValue` can be called recursively and inner data structures might have these values, so 88950 // we just ignore such cases when a field containing FormGroup instance receives `null` or 88951 // `undefined` as a value. 88952 if (value == null 88953 /* both `null` and `undefined` */ 88954 ) return; 88955 Object.keys(value).forEach(name => { 88956 // The compiler cannot see through the uninstantiated conditional type of `this.controls`, so 88957 // `as any` is required. 88958 const control = this.controls[name]; 88959 88960 if (control) { 88961 control.patchValue( 88962 /* Guaranteed to be present, due to the outer forEach. */ 88963 value[name], { 88964 onlySelf: true, 88965 emitEvent: options.emitEvent 88966 }); 88967 } 88968 }); 88969 this.updateValueAndValidity(options); 88970 } 88971 /** 88972 * Resets the `FormGroup`, marks all descendants `pristine` and `untouched` and sets 88973 * the value of all descendants to their default values, or null if no defaults were provided. 88974 * 88975 * You reset to a specific form state by passing in a map of states 88976 * that matches the structure of your form, with control names as keys. The state 88977 * is a standalone value or a form state object with both a value and a disabled 88978 * status. 88979 * 88980 * @param value Resets the control with an initial value, 88981 * or an object that defines the initial value and disabled state. 88982 * 88983 * @param options Configuration options that determine how the control propagates changes 88984 * and emits events when the group is reset. 88985 * * `onlySelf`: When true, each change only affects this control, and not its parent. Default is 88986 * false. 88987 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 88988 * `valueChanges` 88989 * observables emit events with the latest status and value when the control is reset. 88990 * When false, no events are emitted. 88991 * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity 88992 * updateValueAndValidity} method. 88993 * 88994 * @usageNotes 88995 * 88996 * ### Reset the form group values 88997 * 88998 * ```ts 88999 * const form = new FormGroup({ 89000 * first: new FormControl('first name'), 89001 * last: new FormControl('last name') 89002 * }); 89003 * 89004 * console.log(form.value); // {first: 'first name', last: 'last name'} 89005 * 89006 * form.reset({ first: 'name', last: 'last name' }); 89007 * 89008 * console.log(form.value); // {first: 'name', last: 'last name'} 89009 * ``` 89010 * 89011 * ### Reset the form group values and disabled status 89012 * 89013 * ``` 89014 * const form = new FormGroup({ 89015 * first: new FormControl('first name'), 89016 * last: new FormControl('last name') 89017 * }); 89018 * 89019 * form.reset({ 89020 * first: {value: 'name', disabled: true}, 89021 * last: 'last' 89022 * }); 89023 * 89024 * console.log(form.value); // {last: 'last'} 89025 * console.log(form.get('first').status); // 'DISABLED' 89026 * ``` 89027 */ 89028 89029 89030 reset(value = {}, options = {}) { 89031 this._forEachChild((control, name) => { 89032 control.reset(value[name], { 89033 onlySelf: true, 89034 emitEvent: options.emitEvent 89035 }); 89036 }); 89037 89038 this._updatePristine(options); 89039 89040 this._updateTouched(options); 89041 89042 this.updateValueAndValidity(options); 89043 } 89044 /** 89045 * The aggregate value of the `FormGroup`, including any disabled controls. 89046 * 89047 * Retrieves all values regardless of disabled status. 89048 */ 89049 89050 89051 getRawValue() { 89052 return this._reduceChildren({}, (acc, control, name) => { 89053 acc[name] = control.getRawValue(); 89054 return acc; 89055 }); 89056 } 89057 /** @internal */ 89058 89059 89060 _syncPendingControls() { 89061 let subtreeUpdated = this._reduceChildren(false, (updated, child) => { 89062 return child._syncPendingControls() ? true : updated; 89063 }); 89064 89065 if (subtreeUpdated) this.updateValueAndValidity({ 89066 onlySelf: true 89067 }); 89068 return subtreeUpdated; 89069 } 89070 /** @internal */ 89071 89072 89073 _forEachChild(cb) { 89074 Object.keys(this.controls).forEach(key => { 89075 // The list of controls can change (for ex. controls might be removed) while the loop 89076 // is running (as a result of invoking Forms API in `valueChanges` subscription), so we 89077 // have to null check before invoking the callback. 89078 const control = this.controls[key]; 89079 control && cb(control, key); 89080 }); 89081 } 89082 /** @internal */ 89083 89084 89085 _setUpControls() { 89086 this._forEachChild(control => { 89087 control.setParent(this); 89088 89089 control._registerOnCollectionChange(this._onCollectionChange); 89090 }); 89091 } 89092 /** @internal */ 89093 89094 89095 _updateValue() { 89096 this.value = this._reduceValue(); 89097 } 89098 /** @internal */ 89099 89100 89101 _anyControls(condition) { 89102 for (const [controlName, control] of Object.entries(this.controls)) { 89103 if (this.contains(controlName) && condition(control)) { 89104 return true; 89105 } 89106 } 89107 89108 return false; 89109 } 89110 /** @internal */ 89111 89112 89113 _reduceValue() { 89114 let acc = {}; 89115 return this._reduceChildren(acc, (acc, control, name) => { 89116 if (control.enabled || this.disabled) { 89117 acc[name] = control.value; 89118 } 89119 89120 return acc; 89121 }); 89122 } 89123 /** @internal */ 89124 89125 89126 _reduceChildren(initValue, fn) { 89127 let res = initValue; 89128 89129 this._forEachChild((control, name) => { 89130 res = fn(res, control, name); 89131 }); 89132 89133 return res; 89134 } 89135 /** @internal */ 89136 89137 89138 _allControlsDisabled() { 89139 for (const controlName of Object.keys(this.controls)) { 89140 if (this.controls[controlName].enabled) { 89141 return false; 89142 } 89143 } 89144 89145 return Object.keys(this.controls).length > 0 || this.disabled; 89146 } 89147 /** @internal */ 89148 89149 89150 _find(name) { 89151 return this.controls.hasOwnProperty(name) ? this.controls[name] : null; 89152 } 89153 89154} 89155 89156const UntypedFormGroup = FormGroup; 89157 89158const isFormGroup = control => control instanceof FormGroup; 89159/** 89160 * Tracks the value and validity state of a collection of `FormControl` instances, each of which has 89161 * the same value type. 89162 * 89163 * `FormRecord` is very similar to {@link FormGroup}, except it can be used with a dynamic keys, 89164 * with controls added and removed as needed. 89165 * 89166 * `FormRecord` accepts one generic argument, which describes the type of the controls it contains. 89167 * 89168 * @usageNotes 89169 * 89170 * ``` 89171 * let numbers = new FormRecord({bill: new FormControl('415-123-456')}); 89172 * numbers.addControl('bob', new FormControl('415-234-567')); 89173 * numbers.removeControl('bill'); 89174 * ``` 89175 * 89176 * @publicApi 89177 */ 89178 89179 89180class FormRecord extends FormGroup {} 89181 89182const isFormRecord = control => control instanceof FormRecord; 89183/** 89184 * @license 89185 * Copyright Google LLC All Rights Reserved. 89186 * 89187 * Use of this source code is governed by an MIT-style license that can be 89188 * found in the LICENSE file at https://angular.io/license 89189 */ 89190 89191 89192function controlPath(name, parent) { 89193 return [...parent.path, name]; 89194} 89195/** 89196 * Links a Form control and a Form directive by setting up callbacks (such as `onChange`) on both 89197 * instances. This function is typically invoked when form directive is being initialized. 89198 * 89199 * @param control Form control instance that should be linked. 89200 * @param dir Directive that should be linked with a given control. 89201 */ 89202 89203 89204function setUpControl(control, dir) { 89205 if (typeof ngDevMode === 'undefined' || ngDevMode) { 89206 if (!control) _throwError(dir, 'Cannot find control with'); 89207 if (!dir.valueAccessor) _throwError(dir, 'No value accessor for form control with'); 89208 } 89209 89210 setUpValidators(control, dir); 89211 dir.valueAccessor.writeValue(control.value); 89212 89213 if (control.disabled) { 89214 dir.valueAccessor.setDisabledState?.(true); 89215 } 89216 89217 setUpViewChangePipeline(control, dir); 89218 setUpModelChangePipeline(control, dir); 89219 setUpBlurPipeline(control, dir); 89220 setUpDisabledChangeHandler(control, dir); 89221} 89222/** 89223 * Reverts configuration performed by the `setUpControl` control function. 89224 * Effectively disconnects form control with a given form directive. 89225 * This function is typically invoked when corresponding form directive is being destroyed. 89226 * 89227 * @param control Form control which should be cleaned up. 89228 * @param dir Directive that should be disconnected from a given control. 89229 * @param validateControlPresenceOnChange Flag that indicates whether onChange handler should 89230 * contain asserts to verify that it's not called once directive is destroyed. We need this flag 89231 * to avoid potentially breaking changes caused by better control cleanup introduced in #39235. 89232 */ 89233 89234 89235function cleanUpControl(control, dir, validateControlPresenceOnChange = true) { 89236 const noop = () => { 89237 if (validateControlPresenceOnChange && (typeof ngDevMode === 'undefined' || ngDevMode)) { 89238 _noControlError(dir); 89239 } 89240 }; // The `valueAccessor` field is typically defined on FromControl and FormControlName directive 89241 // instances and there is a logic in `selectValueAccessor` function that throws if it's not the 89242 // case. We still check the presence of `valueAccessor` before invoking its methods to make sure 89243 // that cleanup works correctly if app code or tests are setup to ignore the error thrown from 89244 // `selectValueAccessor`. See https://github.com/angular/angular/issues/40521. 89245 89246 89247 if (dir.valueAccessor) { 89248 dir.valueAccessor.registerOnChange(noop); 89249 dir.valueAccessor.registerOnTouched(noop); 89250 } 89251 89252 cleanUpValidators(control, dir); 89253 89254 if (control) { 89255 dir._invokeOnDestroyCallbacks(); 89256 89257 control._registerOnCollectionChange(() => {}); 89258 } 89259} 89260 89261function registerOnValidatorChange(validators, onChange) { 89262 validators.forEach(validator => { 89263 if (validator.registerOnValidatorChange) validator.registerOnValidatorChange(onChange); 89264 }); 89265} 89266/** 89267 * Sets up disabled change handler function on a given form control if ControlValueAccessor 89268 * associated with a given directive instance supports the `setDisabledState` call. 89269 * 89270 * @param control Form control where disabled change handler should be setup. 89271 * @param dir Corresponding directive instance associated with this control. 89272 */ 89273 89274 89275function setUpDisabledChangeHandler(control, dir) { 89276 if (dir.valueAccessor.setDisabledState) { 89277 const onDisabledChange = isDisabled => { 89278 dir.valueAccessor.setDisabledState(isDisabled); 89279 }; 89280 89281 control.registerOnDisabledChange(onDisabledChange); // Register a callback function to cleanup disabled change handler 89282 // from a control instance when a directive is destroyed. 89283 89284 dir._registerOnDestroy(() => { 89285 control._unregisterOnDisabledChange(onDisabledChange); 89286 }); 89287 } 89288} 89289/** 89290 * Sets up sync and async directive validators on provided form control. 89291 * This function merges validators from the directive into the validators of the control. 89292 * 89293 * @param control Form control where directive validators should be setup. 89294 * @param dir Directive instance that contains validators to be setup. 89295 */ 89296 89297 89298function setUpValidators(control, dir) { 89299 const validators = getControlValidators(control); 89300 89301 if (dir.validator !== null) { 89302 control.setValidators(mergeValidators(validators, dir.validator)); 89303 } else if (typeof validators === 'function') { 89304 // If sync validators are represented by a single validator function, we force the 89305 // `Validators.compose` call to happen by executing the `setValidators` function with 89306 // an array that contains that function. We need this to avoid possible discrepancies in 89307 // validators behavior, so sync validators are always processed by the `Validators.compose`. 89308 // Note: we should consider moving this logic inside the `setValidators` function itself, so we 89309 // have consistent behavior on AbstractControl API level. The same applies to the async 89310 // validators logic below. 89311 control.setValidators([validators]); 89312 } 89313 89314 const asyncValidators = getControlAsyncValidators(control); 89315 89316 if (dir.asyncValidator !== null) { 89317 control.setAsyncValidators(mergeValidators(asyncValidators, dir.asyncValidator)); 89318 } else if (typeof asyncValidators === 'function') { 89319 control.setAsyncValidators([asyncValidators]); 89320 } // Re-run validation when validator binding changes, e.g. minlength=3 -> minlength=4 89321 89322 89323 const onValidatorChange = () => control.updateValueAndValidity(); 89324 89325 registerOnValidatorChange(dir._rawValidators, onValidatorChange); 89326 registerOnValidatorChange(dir._rawAsyncValidators, onValidatorChange); 89327} 89328/** 89329 * Cleans up sync and async directive validators on provided form control. 89330 * This function reverts the setup performed by the `setUpValidators` function, i.e. 89331 * removes directive-specific validators from a given control instance. 89332 * 89333 * @param control Form control from where directive validators should be removed. 89334 * @param dir Directive instance that contains validators to be removed. 89335 * @returns true if a control was updated as a result of this action. 89336 */ 89337 89338 89339function cleanUpValidators(control, dir) { 89340 let isControlUpdated = false; 89341 89342 if (control !== null) { 89343 if (dir.validator !== null) { 89344 const validators = getControlValidators(control); 89345 89346 if (Array.isArray(validators) && validators.length > 0) { 89347 // Filter out directive validator function. 89348 const updatedValidators = validators.filter(validator => validator !== dir.validator); 89349 89350 if (updatedValidators.length !== validators.length) { 89351 isControlUpdated = true; 89352 control.setValidators(updatedValidators); 89353 } 89354 } 89355 } 89356 89357 if (dir.asyncValidator !== null) { 89358 const asyncValidators = getControlAsyncValidators(control); 89359 89360 if (Array.isArray(asyncValidators) && asyncValidators.length > 0) { 89361 // Filter out directive async validator function. 89362 const updatedAsyncValidators = asyncValidators.filter(asyncValidator => asyncValidator !== dir.asyncValidator); 89363 89364 if (updatedAsyncValidators.length !== asyncValidators.length) { 89365 isControlUpdated = true; 89366 control.setAsyncValidators(updatedAsyncValidators); 89367 } 89368 } 89369 } 89370 } // Clear onValidatorChange callbacks by providing a noop function. 89371 89372 89373 const noop = () => {}; 89374 89375 registerOnValidatorChange(dir._rawValidators, noop); 89376 registerOnValidatorChange(dir._rawAsyncValidators, noop); 89377 return isControlUpdated; 89378} 89379 89380function setUpViewChangePipeline(control, dir) { 89381 dir.valueAccessor.registerOnChange(newValue => { 89382 control._pendingValue = newValue; 89383 control._pendingChange = true; 89384 control._pendingDirty = true; 89385 if (control.updateOn === 'change') updateControl(control, dir); 89386 }); 89387} 89388 89389function setUpBlurPipeline(control, dir) { 89390 dir.valueAccessor.registerOnTouched(() => { 89391 control._pendingTouched = true; 89392 if (control.updateOn === 'blur' && control._pendingChange) updateControl(control, dir); 89393 if (control.updateOn !== 'submit') control.markAsTouched(); 89394 }); 89395} 89396 89397function updateControl(control, dir) { 89398 if (control._pendingDirty) control.markAsDirty(); 89399 control.setValue(control._pendingValue, { 89400 emitModelToViewChange: false 89401 }); 89402 dir.viewToModelUpdate(control._pendingValue); 89403 control._pendingChange = false; 89404} 89405 89406function setUpModelChangePipeline(control, dir) { 89407 const onChange = (newValue, emitModelEvent) => { 89408 // control -> view 89409 dir.valueAccessor.writeValue(newValue); // control -> ngModel 89410 89411 if (emitModelEvent) dir.viewToModelUpdate(newValue); 89412 }; 89413 89414 control.registerOnChange(onChange); // Register a callback function to cleanup onChange handler 89415 // from a control instance when a directive is destroyed. 89416 89417 dir._registerOnDestroy(() => { 89418 control._unregisterOnChange(onChange); 89419 }); 89420} 89421/** 89422 * Links a FormGroup or FormArray instance and corresponding Form directive by setting up validators 89423 * present in the view. 89424 * 89425 * @param control FormGroup or FormArray instance that should be linked. 89426 * @param dir Directive that provides view validators. 89427 */ 89428 89429 89430function setUpFormContainer(control, dir) { 89431 if (control == null && (typeof ngDevMode === 'undefined' || ngDevMode)) _throwError(dir, 'Cannot find control with'); 89432 setUpValidators(control, dir); 89433} 89434/** 89435 * Reverts the setup performed by the `setUpFormContainer` function. 89436 * 89437 * @param control FormGroup or FormArray instance that should be cleaned up. 89438 * @param dir Directive that provided view validators. 89439 * @returns true if a control was updated as a result of this action. 89440 */ 89441 89442 89443function cleanUpFormContainer(control, dir) { 89444 return cleanUpValidators(control, dir); 89445} 89446 89447function _noControlError(dir) { 89448 return _throwError(dir, 'There is no FormControl instance attached to form control element with'); 89449} 89450 89451function _throwError(dir, message) { 89452 const messageEnd = _describeControlLocation(dir); 89453 89454 throw new Error(`${message} ${messageEnd}`); 89455} 89456 89457function _describeControlLocation(dir) { 89458 const path = dir.path; 89459 if (path && path.length > 1) return `path: '${path.join(' -> ')}'`; 89460 if (path?.[0]) return `name: '${path}'`; 89461 return 'unspecified name attribute'; 89462} 89463 89464function _throwInvalidValueAccessorError(dir) { 89465 const loc = _describeControlLocation(dir); 89466 89467 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1200 89468 /* RuntimeErrorCode.NG_VALUE_ACCESSOR_NOT_PROVIDED */ 89469 , `Value accessor was not provided as an array for form control with ${loc}. ` + `Check that the \`NG_VALUE_ACCESSOR\` token is configured as a \`multi: true\` provider.`); 89470} 89471 89472function isPropertyUpdated(changes, viewModel) { 89473 if (!changes.hasOwnProperty('model')) return false; 89474 const change = changes['model']; 89475 if (change.isFirstChange()) return true; 89476 return !Object.is(viewModel, change.currentValue); 89477} 89478 89479function isBuiltInAccessor(valueAccessor) { 89480 // Check if a given value accessor is an instance of a class that directly extends 89481 // `BuiltInControlValueAccessor` one. 89482 return Object.getPrototypeOf(valueAccessor.constructor) === BuiltInControlValueAccessor; 89483} 89484 89485function syncPendingControls(form, directives) { 89486 form._syncPendingControls(); 89487 89488 directives.forEach(dir => { 89489 const control = dir.control; 89490 89491 if (control.updateOn === 'submit' && control._pendingChange) { 89492 dir.viewToModelUpdate(control._pendingValue); 89493 control._pendingChange = false; 89494 } 89495 }); 89496} // TODO: vsavkin remove it once https://github.com/angular/angular/issues/3011 is implemented 89497 89498 89499function selectValueAccessor(dir, valueAccessors) { 89500 if (!valueAccessors) return null; 89501 if (!Array.isArray(valueAccessors) && (typeof ngDevMode === 'undefined' || ngDevMode)) _throwInvalidValueAccessorError(dir); 89502 let defaultAccessor = undefined; 89503 let builtinAccessor = undefined; 89504 let customAccessor = undefined; 89505 valueAccessors.forEach(v => { 89506 if (v.constructor === DefaultValueAccessor) { 89507 defaultAccessor = v; 89508 } else if (isBuiltInAccessor(v)) { 89509 if (builtinAccessor && (typeof ngDevMode === 'undefined' || ngDevMode)) _throwError(dir, 'More than one built-in value accessor matches form control with'); 89510 builtinAccessor = v; 89511 } else { 89512 if (customAccessor && (typeof ngDevMode === 'undefined' || ngDevMode)) _throwError(dir, 'More than one custom value accessor matches form control with'); 89513 customAccessor = v; 89514 } 89515 }); 89516 if (customAccessor) return customAccessor; 89517 if (builtinAccessor) return builtinAccessor; 89518 if (defaultAccessor) return defaultAccessor; 89519 89520 if (typeof ngDevMode === 'undefined' || ngDevMode) { 89521 _throwError(dir, 'No valid value accessor for form control with'); 89522 } 89523 89524 return null; 89525} 89526 89527function removeListItem$1(list, el) { 89528 const index = list.indexOf(el); 89529 if (index > -1) list.splice(index, 1); 89530} // TODO(kara): remove after deprecation period 89531 89532 89533function _ngModelWarning(name, type, instance, warningConfig) { 89534 if (warningConfig === 'never') return; 89535 89536 if ((warningConfig === null || warningConfig === 'once') && !type._ngModelWarningSentOnce || warningConfig === 'always' && !instance._ngModelWarningSent) { 89537 console.warn(ngModelWarning(name)); 89538 type._ngModelWarningSentOnce = true; 89539 instance._ngModelWarningSent = true; 89540 } 89541} 89542/** 89543 * @license 89544 * Copyright Google LLC All Rights Reserved. 89545 * 89546 * Use of this source code is governed by an MIT-style license that can be 89547 * found in the LICENSE file at https://angular.io/license 89548 */ 89549 89550 89551const formDirectiveProvider$1 = { 89552 provide: ControlContainer, 89553 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => NgForm) 89554}; 89555 89556const resolvedPromise$1 = (() => Promise.resolve())(); 89557/** 89558 * @description 89559 * Creates a top-level `FormGroup` instance and binds it to a form 89560 * to track aggregate form value and validation status. 89561 * 89562 * As soon as you import the `FormsModule`, this directive becomes active by default on 89563 * all `<form>` tags. You don't need to add a special selector. 89564 * 89565 * You optionally export the directive into a local template variable using `ngForm` as the key 89566 * (ex: `#myForm="ngForm"`). This is optional, but useful. Many properties from the underlying 89567 * `FormGroup` instance are duplicated on the directive itself, so a reference to it 89568 * gives you access to the aggregate value and validity status of the form, as well as 89569 * user interaction properties like `dirty` and `touched`. 89570 * 89571 * To register child controls with the form, use `NgModel` with a `name` 89572 * attribute. You may use `NgModelGroup` to create sub-groups within the form. 89573 * 89574 * If necessary, listen to the directive's `ngSubmit` event to be notified when the user has 89575 * triggered a form submission. The `ngSubmit` event emits the original form 89576 * submission event. 89577 * 89578 * In template driven forms, all `<form>` tags are automatically tagged as `NgForm`. 89579 * To import the `FormsModule` but skip its usage in some forms, 89580 * for example, to use native HTML5 validation, add the `ngNoForm` and the `<form>` 89581 * tags won't create an `NgForm` directive. In reactive forms, using `ngNoForm` is 89582 * unnecessary because the `<form>` tags are inert. In that case, you would 89583 * refrain from using the `formGroup` directive. 89584 * 89585 * @usageNotes 89586 * 89587 * ### Listening for form submission 89588 * 89589 * The following example shows how to capture the form values from the "ngSubmit" event. 89590 * 89591 * {@example forms/ts/simpleForm/simple_form_example.ts region='Component'} 89592 * 89593 * ### Setting the update options 89594 * 89595 * The following example shows you how to change the "updateOn" option from its default using 89596 * ngFormOptions. 89597 * 89598 * ```html 89599 * <form [ngFormOptions]="{updateOn: 'blur'}"> 89600 * <input name="one" ngModel> <!-- this ngModel will update on blur --> 89601 * </form> 89602 * ``` 89603 * 89604 * ### Native DOM validation UI 89605 * 89606 * In order to prevent the native DOM form validation UI from interfer
89606ing with Angular's form 89607 * validation, Angular automatically adds the `novalidate` attribute on any `<form>` whenever 89608 * `FormModule` or `ReactiveFormModule` are imported into the application. 89609 * If you want to explicitly enable native DOM validation UI with Angular forms, you can add the 89610 * `ngNativeValidate` attribute to the `<form>` element: 89611 * 89612 * ```html 89613 * <form ngNativeValidate> 89614 * ... 89615 * </form> 89616 * ``` 89617 * 89618 * @ngModule FormsModule 89619 * @publicApi 89620 */ 89621 89622 89623class NgForm extends ControlContainer { 89624 constructor(validators, asyncValidators) { 89625 super(); 89626 /** 89627 * @description 89628 * Returns whether the form submission has been triggered. 89629 */ 89630 89631 this.submitted = false; 89632 this._directives = new Set(); 89633 /** 89634 * @description 89635 * Event emitter for the "ngSubmit" event 89636 */ 89637 89638 this.ngSubmit = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); 89639 this.form = new FormGroup({}, composeValidators(validators), composeAsyncValidators(asyncValidators)); 89640 } 89641 /** @nodoc */ 89642 89643 89644 ngAfterViewInit() { 89645 this._setUpdateStrategy(); 89646 } 89647 /** 89648 * @description 89649 * The directive instance. 89650 */ 89651 89652 89653 get formDirective() { 89654 return this; 89655 } 89656 /** 89657 * @description 89658 * The internal `FormGroup` instance. 89659 */ 89660 89661 89662 get control() { 89663 return this.form; 89664 } 89665 /** 89666 * @description 89667 * Returns an array representing the path to this group. Because this directive 89668 * always lives at the top level of a form, it is always an empty array. 89669 */ 89670 89671 89672 get path() { 89673 return []; 89674 } 89675 /** 89676 * @description 89677 * Returns a map of the controls in this group. 89678 */ 89679 89680 89681 get controls() { 89682 return this.form.controls; 89683 } 89684 /** 89685 * @description 89686 * Method that sets up the control directive in this group, re-calculates its value 89687 * and validity, and adds the instance to the internal list of directives. 89688 * 89689 * @param dir The `NgModel` directive instance. 89690 */ 89691 89692 89693 addControl(dir) { 89694 resolvedPromise$1.then(() => { 89695 const container = this._findContainer(dir.path); 89696 89697 dir.control = container.registerControl(dir.name, dir.control); 89698 setUpControl(dir.control, dir); 89699 dir.control.updateValueAndValidity({ 89700 emitEvent: false 89701 }); 89702 89703 this._directives.add(dir); 89704 }); 89705 } 89706 /** 89707 * @description 89708 * Retrieves the `FormControl` instance from the provided `NgModel` directive. 89709 * 89710 * @param dir The `NgModel` directive instance. 89711 */ 89712 89713 89714 getControl(dir) { 89715 return this.form.get(dir.path); 89716 } 89717 /** 89718 * @description 89719 * Removes the `NgModel` instance from the internal list of directives 89720 * 89721 * @param dir The `NgModel` directive instance. 89722 */ 89723 89724 89725 removeControl(dir) { 89726 resolvedPromise$1.then(() => { 89727 const container = this._findContainer(dir.path); 89728 89729 if (container) { 89730 container.removeControl(dir.name); 89731 } 89732 89733 this._directives.delete(dir); 89734 }); 89735 } 89736 /** 89737 * @description 89738 * Adds a new `NgModelGroup` directive instance to the form. 89739 * 89740 * @param dir The `NgModelGroup` directive instance. 89741 */ 89742 89743 89744 addFormGroup(dir) { 89745 resolvedPromise$1.then(() => { 89746 const container = this._findContainer(dir.path); 89747 89748 const group = new FormGroup({}); 89749 setUpFormContainer(group, dir); 89750 container.registerControl(dir.name, group); 89751 group.updateValueAndValidity({ 89752 emitEvent: false 89753 }); 89754 }); 89755 } 89756 /** 89757 * @description 89758 * Removes the `NgModelGroup` directive instance from the form. 89759 * 89760 * @param dir The `NgModelGroup` directive instance. 89761 */ 89762 89763 89764 removeFormGroup(dir) { 89765 resolvedPromise$1.then(() => { 89766 const container = this._findContainer(dir.path); 89767 89768 if (container) { 89769 container.removeControl(dir.name); 89770 } 89771 }); 89772 } 89773 /** 89774 * @description 89775 * Retrieves the `FormGroup` for a provided `NgModelGroup` directive instance 89776 * 89777 * @param dir The `NgModelGroup` directive instance. 89778 */ 89779 89780 89781 getFormGroup(dir) { 89782 return this.form.get(dir.path); 89783 } 89784 /** 89785 * Sets the new value for the provided `NgControl` directive. 89786 * 89787 * @param dir The `NgControl` directive instance. 89788 * @param value The new value for the directive's control. 89789 */ 89790 89791 89792 updateModel(dir, value) { 89793 resolvedPromise$1.then(() => { 89794 const ctrl = this.form.get(dir.path); 89795 ctrl.setValue(value); 89796 }); 89797 } 89798 /** 89799 * @description 89800 * Sets the value for this `FormGroup`. 89801 * 89802 * @param value The new value 89803 */ 89804 89805 89806 setValue(value) { 89807 this.control.setValue(value); 89808 } 89809 /** 89810 * @description 89811 * Method called when the "submit" event is triggered on the form. 89812 * Triggers the `ngSubmit` emitter to emit the "submit" event as its payload. 89813 * 89814 * @param $event The "submit" event object 89815 */ 89816 89817 89818 onSubmit($event) { 89819 this.submitted = true; 89820 syncPendingControls(this.form, this._directives); 89821 this.ngSubmit.emit($event); // Forms with `method="dialog"` have some special behavior 89822 // that won't reload the page and that shouldn't be prevented. 89823 89824 return $event?.target?.method === 'dialog'; 89825 } 89826 /** 89827 * @description 89828 * Method called when the "reset" event is triggered on the form. 89829 */ 89830 89831 89832 onReset() { 89833 this.resetForm(); 89834 } 89835 /** 89836 * @description 89837 * Resets the form to an initial value and resets its submitted status. 89838 * 89839 * @param value The new value for the form. 89840 */ 89841 89842 89843 resetForm(value = undefined) { 89844 this.form.reset(value); 89845 this.submitted = false;
89846 } 89847 89848 _setUpdateStrategy() { 89849 if (this.options && this.options.updateOn != null) { 89850 this.form._updateOn = this.options.updateOn; 89851 } 89852 } 89853 89854 _findContainer(path) { 89855 path.pop(); 89856 return path.length ? this.form.get(path) : this.form; 89857 } 89858 89859} 89860 89861NgForm.ɵfac = function NgForm_Factory(t) { 89862 return new (t || NgForm)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10)); 89863}; 89864 89865NgForm.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 89866 type: NgForm, 89867 selectors: [["form", 3, "ngNoForm", "", 3, "formGroup", ""], ["ng-form"], ["", "ngForm", ""]], 89868 hostBindings: function NgForm_HostBindings(rf, ctx) { 89869 if (rf & 1) { 89870 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("submit", function NgForm_submit_HostBindingHandler($event) { 89871 return ctx.onSubmit($event); 89872 })("reset", function NgForm_reset_HostBindingHandler() { 89873 return ctx.onReset(); 89874 }); 89875 } 89876 }, 89877 inputs: { 89878 options: ["ngFormOptions", "options"] 89879 }, 89880 outputs: { 89881 ngSubmit: "ngSubmit" 89882 }, 89883 exportAs: ["ngForm"], 89884 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([formDirectiveProvider$1]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 89885}); 89886 89887(function () { 89888 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgForm, [{ 89889 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 89890 args: [{ 89891 selector: 'form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]', 89892 providers: [formDirectiveProvider$1], 89893 host: { 89894 '(submit)': 'onSubmit($event)', 89895 '(reset)': 'onReset()' 89896 }, 89897 outputs: ['ngSubmit'], 89898 exportAs: 'ngForm' 89899 }] 89900 }], function () { 89901 return [{ 89902 type: undefined, 89903 decorators: [{ 89904 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 89905 }, { 89906 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 89907 }, { 89908 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 89909 args: [NG_VALIDATORS] 89910 }] 89911 }, { 89912 type: undefined, 89913 decorators: [{ 89914 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 89915 }, { 89916 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 89917 }, { 89918 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 89919 args: [NG_ASYNC_VALIDATORS] 89920 }] 89921 }]; 89922 }, { 89923 options: [{ 89924 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 89925 args: ['ngFormOptions'] 89926 }] 89927 }); 89928})(); 89929/** 89930 * @license 89931 * Copyright Google LLC All Rights Reserved. 89932 * 89933 * Use of this source code is governed by an MIT-style license that can be 89934 * found in the LICENSE file at https://angular.io/license 89935 */ 89936 89937 89938function removeListItem(list, el) { 89939 const index = list.indexOf(el); 89940 if (index > -1) list.splice(index, 1); 89941} 89942/** 89943 * @license 89944 * Copyright Google LLC All Rights Reserved. 89945 * 89946 * Use of this source code is governed by an MIT-style license that can be 89947 * found in the LICENSE file at https://angular.io/license 89948 */ 89949 89950 89951function isFormControlState(formState) { 89952 return typeof formState === 'object' && formState !== null && Object.keys(formState).length === 2 && 'value' in formState && 'disabled' in formState; 89953} 89954 89955const FormControl = class FormControl extends AbstractControl { 89956 constructor( // formState and defaultValue will only be null if T is nullable 89957 formState = null, validatorOrOpts, asyncValidator) { 89958 super(pickValidators(validatorOrOpts), pickAsyncValidators(asyncValidator, validatorOrOpts)); 89959 /** @publicApi */ 89960 89961 this.defaultValue = null; 89962 /** @internal */ 89963 89964 this._onChange = []; 89965 /** @internal */ 89966 89967 this._pendingChange = false; 89968 89969 this._applyFormState(formState); 89970 89971 this._setUpdateStrategy(validatorOrOpts); 89972 89973 this._initObservables(); 89974 89975 this.updateValueAndValidity({ 89976 onlySelf: true, 89977 // If `asyncValidator` is present, it will trigger control status change from `PENDING` to 89978 // `VALID` or `INVALID`. 89979 // The status should be broadcasted via the `statusChanges` observable, so we set 89980 // `emitEvent` to `true` to allow that during the control creation process. 89981 emitEvent: !!this.asyncValidator 89982 }); 89983 89984 if (isOptionsObj(validatorOrOpts) && (validatorOrOpts.nonNullable || validatorOrOpts.initialValueIsDefault)) { 89985 if (isFormControlState(formState)) { 89986 this.defaultValue = formState.value; 89987 } else { 89988 this.defaultValue = formState; 89989 } 89990 } 89991 } 89992 89993 setValue(value, options = {}) { 89994 this.value = this._pendingValue = value; 89995 89996 if (this._onChange.length && options.emitModelToViewChange !== false) { 89997 this._onChange.forEach(changeFn => changeFn(this.value, options.emitViewToModelChange !== false)); 89998 } 89999
90000 this.updateValueAndValidity(options); 90001 } 90002 90003 patchValue(value, options = {}) { 90004 this.setValue(value, options); 90005 } 90006 90007 reset(formState = this.defaultValue, options = {}) { 90008 this._applyFormState(formState); 90009 90010 this.markAsPristine(options); 90011 this.markAsUntouched(options); 90012 this.setValue(this.value, options); 90013 this._pendingChange = false; 90014 } 90015 /** @internal */ 90016 90017 90018 _updateValue() {} 90019 /** @internal */ 90020 90021 90022 _anyControls(condition) { 90023 return false; 90024 } 90025 /** @internal */ 90026 90027 90028 _allControlsDisabled() { 90029 return this.disabled; 90030 } 90031 90032 registerOnChange(fn) { 90033 this._onChange.push(fn); 90034 } 90035 /** @internal */ 90036 90037 90038 _unregisterOnChange(fn) { 90039 removeListItem(this._onChange, fn); 90040 } 90041 90042 registerOnDisabledChange(fn) { 90043 this._onDisabledChange.push(fn); 90044 } 90045 /** @internal */ 90046 90047 90048 _unregisterOnDisabledChange(fn) { 90049 removeListItem(this._onDisabledChange, fn); 90050 } 90051 /** @internal */ 90052 90053 90054 _forEachChild(cb) {} 90055 /** @internal */ 90056 90057 90058 _syncPendingControls() { 90059 if (this.updateOn === 'submit') { 90060 if (this._pendingDirty) this.markAsDirty(); 90061 if (this._pendingTouched) this.markAsTouched(); 90062 90063 if (this._pendingChange) { 90064 this.setValue(this._pendingValue, { 90065 onlySelf: true, 90066 emitModelToViewChange: false 90067 }); 90068 return true; 90069 } 90070 } 90071 90072 return false; 90073 } 90074 90075 _applyFormState(formState) { 90076 if (isFormControlState(formState)) { 90077 this.value = this._pendingValue = formState.value; 90078 formState.disabled ? this.disable({ 90079 onlySelf: true, 90080 emitEvent: false 90081 }) : this.enable({ 90082 onlySelf: true, 90083 emitEvent: false 90084 }); 90085 } else { 90086 this.value = this._pendingValue = formState; 90087 } 90088 } 90089 90090}; 90091const UntypedFormControl = FormControl; 90092 90093const isFormControl = control => control instanceof FormControl; 90094/** 90095 * @license 90096 * Copyright Google LLC All Rights Reserved. 90097 * 90098 * Use of this source code is governed by an MIT-style license that can be 90099 * found in the LICENSE file at https://angular.io/license 90100 */ 90101 90102/** 90103 * @description 90104 * A base class for code shared between the `NgModelGroup` and `FormGroupName` directives. 90105 * 90106 * @publicApi 90107 */ 90108 90109 90110class AbstractFormGroupDirective extends ControlContainer { 90111 /** @nodoc */ 90112 ngOnInit() { 90113 this._checkParentType(); // Register the group with its parent group. 90114 90115 90116 this.formDirective.addFormGroup(this); 90117 } 90118 /** @nodoc */ 90119 90120 90121 ngOnDestroy() { 90122 if (this.formDirective) { 90123 // Remove the group from its parent group. 90124 this.formDirective.removeFormGroup(this); 90125 } 90126 } 90127 /** 90128 * @description 90129 * The `FormGroup` bound to this directive. 90130 */ 90131 90132 90133 get control() { 90134 return this.formDirective.getFormGroup(this); 90135 } 90136 /** 90137 * @description 90138 * The path to this group from the top-level directive. 90139 */ 90140 90141 90142 get path() { 90143 return controlPath(this.name == null ? this.name : this.name.toString(), this._parent); 90144 } 90145 /** 90146 * @description 90147 * The top-level directive for this group if present, otherwise null. 90148 */ 90149 90150 90151 get formDirective() { 90152 return this._parent ? this._parent.formDirective : null; 90153 } 90154 /** @internal */ 90155 90156 90157 _checkParentType() {} 90158 90159} 90160 90161AbstractFormGroupDirective.ɵfac = /* @__PURE__ */function () { 90162 let ɵAbstractFormGroupDirective_BaseFactory; 90163 return function AbstractFormGroupDirective_Factory(t) { 90164 return (ɵAbstractFormGroupDirective_BaseFactory || (ɵAbstractFormGroupDirective_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](AbstractFormGroupDirective)))(t || AbstractFormGroupDirective); 90165 }; 90166}(); 90167 90168AbstractFormGroupDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 90169 type: AbstractFormGroupDirective, 90170 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 90171}); 90172 90173(function () { 90174 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](AbstractFormGroupDirective, [{ 90175 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive 90176 }], null, null); 90177})(); 90178/** 90179 * @license 90180 * Copyright Google LLC All Rights Reserved. 90181 * 90182 * Use of this source code is governed by an MIT-style license that can be 90183 * found in the LICENSE file at https://angular.io/license 90184 */ 90185 90186 90187function modelParentException() { 90188 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1350 90189 /* RuntimeErrorCode.NGMODEL_IN_FORM_GROUP */ 90190 , ` 90191 ngModel cannot be used to register form controls with a parent formGroup directive. Try using 90192 formGroup's partner directive "formControlName" instead. Example: 90193 90194 ${formControlNameExample} 90195 90196 Or, if you'd like to avoid registering this form control, indicate that it's standalone in ngModelOptions: 90197 90198 Example: 90199 90200 ${ngModelWithFormGroupExample}`); 90201} 90202 90203function formGroupNameException() { 90204 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1351 90205 /* RuntimeErrorCode.NGMODEL_IN_FORM_GROUP_NAME */ 90206 , ` 90207 ngModel cannot be used to register form controls with a parent formGroupName or formArrayName directive. 90208 90209 Option 1: Use formControlName instead of ngModel (reactive strategy): 90210 90211 ${formGroupNameExample} 90212 90213 Option 2: Update ngModel's parent be ngModelGroup (template-driven strategy): 90214 90215 ${ngModelGroupExample}`); 90216} 90217 90218function missingNameException() { 90219 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1352 90220 /* RuntimeErrorCode.NGMODEL_WITHOUT_NAME */ 90221 , `If ngModel is used within a form tag, either the name attribute must be set or the form 90222 control must be defined as 'standalone' in ngModelOptions. 90223 90224 Example 1: <input [(ngModel)]="person.firstName" name="first"> 90225 Example 2: <input [(ngModel)]="person.firstName" [ngModelOptions]="{standalone: true}">`); 90226} 90227 90228function modelGroupParentException() { 90229 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1353 90230 /* RuntimeErrorCode.NGMODELGROUP_IN_FORM_GROUP */ 90231 , ` 90232 ngModelGroup cannot be used with a parent formGroup directive. 90233 90234 Option 1: Use formGroupName instead of ngModelGroup (reactive strategy): 90235 90236 ${formGroupNameExample} 90237 90238 Option 2: Use a regular form tag instead of the formGroup directive (template-driven strategy): 90239 90240 ${ngModelGroupExample}`); 90241} 90242/** 90243 * @license 90244 * Copyright Google LLC All Rights Reserved. 90245 * 90246 * Use of this source code is governed by an MIT-style license that can be 90247 * found in the LICENSE file at https://angular.io/license 90248 */ 90249 90250 90251const modelGroupProvider = { 90252 provide: ControlContainer, 90253 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => NgModelGroup) 90254}; 90255/** 90256 * @description 90257 * Creates and binds a `FormGroup` instance to a DOM element. 90258 * 90259 * This directive can only be used as a child of `NgForm` (within `<form>` tags). 90260 * 90261 * Use this directive to validate a sub-group of your form separately from the 90262 * rest of your form, or if some values in your domain model make more sense
90263 * to consume together in a nested object. 90264 * 90265 * Provide a name for the sub-group and it will become the key 90266 * for the sub-group in the form's full value. If you need direct access, export the directive into 90267 * a local template variable using `ngModelGroup` (ex: `#myGroup="ngModelGroup"`). 90268 * 90269 * @usageNotes 90270 * 90271 * ### Consuming controls in a grouping 90272 * 90273 * The following example shows you how to combine controls together in a sub-group 90274 * of the form. 90275 * 90276 * {@example forms/ts/ngModelGroup/ng_model_group_example.ts region='Component'} 90277 * 90278 * @ngModule FormsModule 90279 * @publicApi 90280 */ 90281 90282class NgModelGroup extends AbstractFormGroupDirective { 90283 constructor(parent, validators, asyncValidators) { 90284 super(); 90285 this._parent = parent; 90286 90287 this._setValidators(validators); 90288 90289 this._setAsyncValidators(asyncValidators); 90290 } 90291 /** @internal */ 90292 90293 90294 _checkParentType() { 90295 if (!(this._parent instanceof NgModelGroup) && !(this._parent instanceof NgForm) && (typeof ngDevMode === 'undefined' || ngDevMode)) { 90296 throw modelGroupParentException(); 90297 } 90298 } 90299 90300} 90301 90302NgModelGroup.ɵfac = function NgModelGroup_Factory(t) { 90303 return new (t || NgModelGroup)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ControlContainer, 5), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10)); 90304}; 90305 90306NgModelGroup.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 90307 type: NgModelGroup, 90308 selectors: [["", "ngModelGroup", ""]], 90309 inputs: { 90310 name: ["ngModelGroup", "name"] 90311 }, 90312 exportAs: ["ngModelGroup"], 90313 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([modelGroupProvider]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 90314}); 90315 90316(function () { 90317 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgModelGroup, [{ 90318 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 90319 args: [{ 90320 selector: '[ngModelGroup]', 90321 providers: [modelGroupProvider], 90322 exportAs: 'ngModelGroup' 90323 }] 90324 }], function () { 90325 return [{ 90326 type: ControlContainer, 90327 decorators: [{ 90328 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host 90329 }, { 90330 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.SkipSelf 90331 }] 90332 }, { 90333 type: undefined, 90334 decorators: [{ 90335 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 90336 }, { 90337 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 90338 }, { 90339 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 90340 args: [NG_VALIDATORS] 90341 }] 90342 }, { 90343 type: undefined, 90344 decorators: [{ 90345 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 90346 }, { 90347 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 90348 }, { 90349 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 90350 args: [NG_ASYNC_VALIDATORS] 90351 }] 90352 }]; 90353 }, { 90354 name: [{ 90355 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 90356 args: ['ngModelGroup'] 90357 }] 90358 }); 90359})(); 90360/** 90361 * @license 90362 * Copyright Google LLC All Rights Reserved. 90363 * 90364 * Use of this source code is governed by an MIT-style license that can be 90365 * found in the LICENSE file at https://angular.io/license 90366 */ 90367 90368 90369const formControlBinding$1 = { 90370 provide: NgControl, 90371 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => NgModel) 90372}; 90373/** 90374 * `ngModel` forces an additional change detection run when its inputs change: 90375 * E.g.: 90376 * ``` 90377 * <div>{{myModel.valid}}</div> 90378 * <input [(ngModel)]="myValue" #myModel="ngModel"> 90379 * ``` 90380 * I.e. `ngModel` can export itself on the element and then be used in the template. 90381 * Normally, this would result in expressions before the `input` that use the exported directive 90382 * to have an old value as they have been 90383 * dirty checked before. As this is a very common case for `ngModel`, we added this second change 90384 * detection run. 90385 * 90386 * Notes: 90387 * - this is just one extra run no matter how many `ngModel`s have been changed. 90388 * - this is a general problem when using `exportAs` for directives! 90389 */ 90390 90391const resolvedPromise = (() => Promise.resolve())(); 90392/** 90393 * @description 90394 * Creates a `FormControl` instance from a domain model and binds it 90395 * to a form control element. 90396 * 90397 * The `FormControl` instance tracks the value, user interaction, and 90398 * validation status of the control and keeps the view synced with the model. If used 90399 * within a parent form, the directive also registers itself with the form as a child 90400 * control. 90401 * 90402 * This directive is used by itself or as part of a larger form. Use the 90403 * `ngModel` selector to activate it. 90404 * 90405 * It accepts a domain model as an optional `Input`. If you have a one-way binding 90406 * to `ngModel` with `[]` syntax, changing the domain model's value in the component 90407 * class sets the value in the view. If you have a two-way binding with `[()]` syntax 90408 * (also known as 'banana-in-a-box syntax'), the value in the UI always syncs back to 90409 * the domain model in your class. 90410 * 90411 * To inspect the properties of the associated `FormControl` (like the validity state), 90412 * export the directive into a local template variable using `ngModel` as the key (ex: 90413 * `#myVar="ngModel"`). You can then access the control using the directive's `control` property.
90414 * However, the most commonly used properties (like `valid` and `dirty`) also exist on the control 90415 * for direct access. See a full list of properties directly available in 90416 * `AbstractControlDirective`. 90417 * 90418 * @see `RadioControlValueAccessor` 90419 * @see `SelectControlValueAccessor` 90420 * 90421 * @usageNotes 90422 * 90423 * ### Using ngModel on a standalone control 90424 * 90425 * The following examples show a simple standalone control using `ngModel`: 90426 * 90427 * {@example forms/ts/simpleNgModel/simple_ng_model_example.ts region='Component'} 90428 * 90429 * When using the `ngModel` within `<form>` tags, you'll also need to supply a `name` attribute 90430 * so that the control can be registered with the parent form under that name. 90431 * 90432 * In the context of a parent form, it's often unnecessary to include one-way or two-way binding, 90433 * as the parent form syncs the value for you. You access its properties by exporting it into a 90434 * local template variable using `ngForm` such as (`#f="ngForm"`). Use the variable where 90435 * needed on form submission. 90436 * 90437 * If you do need to populate initial values into your form, using a one-way binding for 90438 * `ngModel` tends to be sufficient as long as you use the exported form's value rather 90439 * than the domain model's value on submit. 90440 * 90441 * ### Using ngModel within a form 90442 * 90443 * The following example shows controls using `ngModel` within a form: 90444 * 90445 * {@example forms/ts/simpleForm/simple_form_example.ts region='Component'} 90446 * 90447 * ### Using a standalone ngModel within a group 90448 * 90449 * The following example shows you how to use a standalone ngModel control 90450 * within a form. This controls the display of the form, but doesn't contain form data. 90451 * 90452 * ```html 90453 * <form> 90454 * <input name="login" ngModel placeholder="Login"> 90455 * <input type="checkbox" ngModel [ngModelOptions]="{standalone: true}"> Show more options? 90456 * </form> 90457 * <!-- form value: {login: ''} --> 90458 * ``` 90459 * 90460 * ### Setting the ngModel `name` attribute through options 90461 * 90462 * The following example shows you an alternate way to set the name attribute. Here, 90463 * an attribute identified as name is used within a custom form control component. To still be able 90464 * to specify the NgModel's name, you must specify it using the `ngModelOptions` input instead. 90465 * 90466 * ```html 90467 * <form> 90468 * <my-custom-form-control name="Nancy" ngModel [ngModelOptions]="{name: 'user'}"> 90469 * </my-custom-form-control> 90470 * </form> 90471 * <!-- form value: {user: ''} --> 90472 * ``` 90473 * 90474 * @ngModule FormsModule 90475 * @publicApi 90476 */ 90477 90478 90479class NgModel extends NgControl { 90480 constructor(parent, validators, asyncValidators, valueAccessors, _changeDetectorRef) { 90481 super(); 90482 this._changeDetectorRef = _changeDetectorRef; 90483 this.control = new FormControl(); 90484 /** @internal */ 90485 90486 this._registered = false; 90487 /** 90488 * @description 90489 * Event emitter for producing the `ngModelChange` event after 90490 * the view model updates. 90491 */ 90492 90493 this.update = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); 90494 this._parent = parent; 90495 90496 this._setValidators(validators); 90497 90498 this._setAsyncValidators(asyncValidators); 90499 90500 this.valueAccessor = selectValueAccessor(this, valueAccessors); 90501 } 90502 /** @nodoc */ 90503 90504 90505 ngOnChanges(changes) { 90506 this._checkForErrors(); 90507 90508 if (!this._registered || 'name' in changes) { 90509 if (this._registered) { 90510 this._checkName(); 90511 90512 if (this.formDirective) { 90513 // We can't call `formDirective.removeControl(this)`, because the `name` has already been 90514 // changed. We also can't reset the name temporarily since the logic in `removeControl` 90515 // is inside a promise and it won't run immediately. We work around it by giving it an 90516 // object with the same shape instead. 90517 const oldName = changes['name'].previousValue; 90518 this.formDirective.removeControl({ 90519 name: oldName, 90520 path: this._getPath(oldName) 90521 }); 90522 } 90523 } 90524 90525 this._setUpControl(); 90526 } 90527 90528 if ('isDisabled' in changes) { 90529 this._updateDisabled(changes); 90530 } 90531 90532 if (isPropertyUpdated(changes, this.viewModel)) { 90533 this._updateValue(this.model); 90534 90535 this.viewModel = this.model; 90536 } 90537 } 90538 /** @nodoc */ 90539 90540 90541 ngOnDestroy() { 90542 this.formDirective && this.formDirective.removeControl(this); 90543 } 90544 /** 90545 * @description 90546 * Returns an array that represents the path from the top-level form to this control. 90547 * Each index is the string name of the control on that level. 90548 */ 90549 90550 90551 get path() { 90552 return this._getPath(this.name); 90553 } 90554 /** 90555 * @description 90556 * The top-level directive for this control if present, otherwise null. 90557 */ 90558 90559 90560 get formDirective() { 90561 return this._parent ? this._parent.formDirective : null; 90562 } 90563 /** 90564 * @description 90565 * Sets the new value for the view model and emits an `ngModelChange` event. 90566 * 90567 * @param newValue The new value emitted by `ngModelChange`. 90568 */ 90569 90570 90571 viewToModelUpdate(newValue) { 90572 this.viewModel = newValue; 90573 this.update.emit(newValue); 90574 } 90575 90576 _setUpControl() { 90577 this._setUpdateStrategy(); 90578 90579 this._isStandalone() ? this._setUpStandalone() : this.formDirective.addControl(this); 90580 this._registered = true; 90581 } 90582 90583 _setUpdateStrategy() { 90584 if (this.options && this.options.updateOn != null) { 90585 this.control._updateOn = this.options.updateOn; 90586 } 90587 } 90588 90589 _isStandalone() { 90590 return !this._parent || !!(this.options && this.options.standalone); 90591 } 90592 90593 _setUpStandalone() { 90594 setUpControl(this.control, this); 90595 this.control.updateValueAndValidity({ 90596 emitEvent: false 90597 }); 90598 } 90599 90600 _checkForErrors() { 90601 if (!this._isStandalone()) { 90602 this._checkParentType(); 90603 } 90604 90605 this._checkName(); 90606 } 90607 90608 _checkParentType() { 90609 if (typeof ngDevMode === 'undefined' || ngDevMode) { 90610 if (!(this._parent instanceof NgModelGroup) && this._parent instanceof AbstractFormGroupDirective) { 90611 throw formGroupNameException(); 90612 } else if (!(this._parent instanceof NgModelGroup) && !(this._parent instanceof NgForm)) { 90613 throw modelParentException(); 90614 } 90615 } 90616 } 90617 90618 _checkName() { 90619 if (this.options && this.options.name) this.name = this.options.name; 90620 90621 if (!this._isStandalone() && !this.name && (typeof ngDevMode === 'undefined' || ngDevMode)) { 90622 throw missingNameException(); 90623 } 90624 } 90625
90626 _updateValue(value) { 90627 resolvedPromise.then(() => { 90628 this.control.setValue(value, { 90629 emitViewToModelChange: false 90630 }); 90631 this._changeDetectorRef?.markForCheck(); 90632 }); 90633 } 90634 90635 _updateDisabled(changes) { 90636 const disabledValue = changes['isDisabled'].currentValue; // checking for 0 to avoid breaking change 90637 90638 const isDisabled = disabledValue !== 0 && (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"])(disabledValue); 90639 resolvedPromise.then(() => { 90640 if (isDisabled && !this.control.disabled) { 90641 this.control.disable(); 90642 } else if (!isDisabled && this.control.disabled) { 90643 this.control.enable(); 90644 } 90645 90646 this._changeDetectorRef?.markForCheck(); 90647 }); 90648 } 90649 90650 _getPath(controlName) { 90651 return this._parent ? controlPath(controlName, this._parent) : [controlName]; 90652 } 90653 90654} 90655 90656NgModel.ɵfac = function NgModel_Factory(t) { 90657 return new (t || NgModel)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ControlContainer, 9), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALUE_ACCESSOR, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef, 8)); 90658}; 90659 90660NgModel.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 90661 type: NgModel, 90662 selectors: [["", "ngModel", "", 3, "formControlName", "", 3, "formControl", ""]], 90663 inputs: { 90664 name: "name", 90665 isDisabled: ["disabled", "isDisabled"], 90666 model: ["ngModel", "model"], 90667 options: ["ngModelOptions", "options"] 90668 }, 90669 outputs: { 90670 update: "ngModelChange" 90671 }, 90672 exportAs: ["ngModel"], 90673 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([formControlBinding$1]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"], _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]] 90674}); 90675 90676(function () { 90677 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgModel, [{ 90678 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 90679 args: [{ 90680 selector: '[ngModel]:not([formControlName]):not([formControl])', 90681 providers: [formControlBinding$1], 90682 exportAs: 'ngModel' 90683 }] 90684 }], function () { 90685 return [{ 90686 type: ControlContainer, 90687 decorators: [{ 90688 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 90689 }, { 90690 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host 90691 }] 90692 }, { 90693 type: undefined, 90694 decorators: [{ 90695 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 90696 }, { 90697 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 90698 }, { 90699 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 90700 args: [NG_VALIDATORS] 90701 }] 90702 }, { 90703 type: undefined, 90704 decorators: [{ 90705 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 90706 }, { 90707 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 90708 }, { 90709 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 90710 args: [NG_ASYNC_VALIDATORS] 90711 }] 90712 }, { 90713 type: undefined, 90714 decorators: [{ 90715 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 90716 }, { 90717 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 90718 }, { 90719 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 90720 args: [NG_VALUE_ACCESSOR] 90721 }] 90722 }, { 90723 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef, 90724 decorators: [{ 90725 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 90726 }, { 90727 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 90728 args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef] 90729 }] 90730 }]; 90731 }, { 90732 name: [{ 90733 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 90734 }], 90735 isDisabled: [{ 90736 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 90737 args: ['disabled'] 90738 }], 90739 model: [{ 90740 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 90741 args: ['ngModel'] 90742 }], 90743 options: [{ 90744 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 90745 args: ['ngModelOptions'] 90746 }], 90747 update: [{ 90748 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output, 90749 args: ['ngModelChange'] 90750 }] 90751 }); 90752})(); 90753/** 90754 * @license 90755 * Copyright Google LLC All Rights Reserved. 90756 * 90757 * Use of this source code is governed by an MIT-style license that can be 90758 * found in the LICENSE file at https://angular.io/license 90759 */ 90760 90761/** 90762 * @description 90763 * 90764 * Adds `novalidate` attribute to all forms by default. 90765 * 90766 * `novalidate` is used to disable browser's native form validation. 90767 * 90768 * If you want to use native validation with Angular forms, just add `ngNativeValidate` attribute: 90769 * 90770 * ``` 90771 * <form ngNativeValidate></form> 90772 * ``` 90773 * 90774 * @publicApi 90775 * @ngModule ReactiveFormsModule 90776 * @ngModule FormsModule 90777 */ 90778 90779 90780class ɵNgNoValidate {} 90781 90782ɵNgNoValidate.ɵfac = function ɵNgNoValidate_Factory(t) { 90783 return new (t || ɵNgNoValidate)(); 90784}; 90785 90786ɵNgNoValidate.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 90787 type: ɵNgNoValidate, 90788 selectors: [["form", 3, "ngNoForm", "", 3, "ngNativeValidate", ""]], 90789 hostAttrs: ["novalidate", ""] 90790}); 90791 90792(function () { 90793 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ɵNgNoValidate, [{ 90794 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 90795 args: [{ 90796 selector: 'form:not([ngNoForm]):not([ngNativeValidate])', 90797 host: { 90798 'novalidate': '' 90799 } 90800 }] 90801 }], null, null); 90802})(); 90803/** 90804 * @license 90805 * Copyright Google LLC All Rights Reserved. 90806 * 90807 * Use of this source code is governed by an MIT-style license that can be 90808 * found in the LICENSE file at https://angular.io/license 90809 */ 90810 90811 90812const NUMBER_VALUE_ACCESSOR = { 90813 provide: NG_VALUE_ACCESSOR, 90814 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => NumberValueAccessor), 90815 multi: true 90816}; 90817/** 90818 * @description 90819 * The `ControlValueAccessor` for writing a number value and listening to number input changes. 90820 * The value accessor is used by the `FormControlDirective`, `FormControlName`, and `NgModel` 90821 * directives. 90822 * 90823 * @usageNotes 90824 * 90825 * ### Using a number input with a reactive form. 90826 * 90827 * The following example shows how to use a number input with a reactive form. 90828 * 90829 * ```ts 90830 * const totalCountControl = new FormControl(); 90831 * ``` 90832 * 90833 * ``` 90834 * <input type="number" [formControl]="totalCountControl"> 90835 * ``` 90836 * 90837 * @ngModule ReactiveFormsModule 90838 * @ngModule FormsModule 90839 * @publicApi 90840 */ 90841 90842class NumberValueAccessor extends BuiltInControlValueAccessor { 90843 /** 90844 * Sets the "value" property on the input element. 90845 * @nodoc 90846 */ 90847 writeValue(value) { 90848 // The value needs to be normalized for IE9, otherwise it is set to 'null' when null 90849 const normalizedValue = value == null ? '' : value; 90850 this.setProperty('value', normalizedValue); 90851 } 90852 /** 90853 * Registers a function called when the control value changes. 90854 * @nodoc 90855 */ 90856 90857 90858 registerOnChange(fn) { 90859 this.onChange = value => { 90860 fn(value == '' ? null : parseFloat(value)); 90861 }; 90862 } 90863 90864} 90865 90866NumberValueAccessor.ɵfac = /* @__PURE__ */function () { 90867 let ɵNumberValueAccessor_BaseFactory; 90868 return function NumberValueAccessor_Factory(t) { 90869 return (ɵNumberValueAccessor_BaseFactory || (ɵNumberValueAccessor_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](NumberValueAccessor)))(t || NumberValueAccessor); 90870 }; 90871}(); 90872 90873NumberValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 90874 type: NumberValueAccessor, 90875 selectors: [["input", "type", "number", "formControlName", ""], ["input", "type", "number", "formControl", ""], ["input", "type", "number", "ngModel", ""]], 90876 hostBindings: function NumberValueAccessor_HostBindings(rf, ctx) { 90877 if (rf & 1) { 90878 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("input", function NumberValueAccessor_input_HostBindingHandler($event) { 90879 return ctx.onChange($event.target.value); 90880 })("blur", function NumberValueAccessor_blur_HostBindingHandler() { 90881 return ctx.onTouched(); 90882 }); 90883 } 90884 }, 90885 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([NUMBER_VALUE_ACCESSOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 90886}); 90887 90888(function () { 90889 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NumberValueAccessor, [{ 90890 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 90891 args: [{ 90892 selector: 'input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]', 90893 host: { 90894 '(input)': 'onChange($event.target.value)', 90895 '(blur)': 'onTouched()' 90896 }, 90897 providers: [NUMBER_VALUE_ACCESSOR] 90898 }] 90899 }], null, null); 90900})(); 90901/** 90902 * @license 90903 * Copyright Google LLC All Rights Reserved. 90904 * 90905 * Use of this source code is governed by an MIT-style license that can be 90906 * found in the LICENSE file at https://angular.io/license 90907 */ 90908 90909 90910const RADIO_VALUE_ACCESSOR = { 90911 provide: NG_VALUE_ACCESSOR, 90912 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => RadioControlValueAccessor), 90913 multi: true 90914}; 90915 90916function throwNameError() { 90917 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1202 90918 /* RuntimeErrorCode.NAME_AND_FORM_CONTROL_NAME_MUST_MATCH */ 90919 , ` 90920 If you define both a name and a formControlName attribute on your radio button, their values 90921 must match. Ex: <input type="radio" formControlName="food" name="food"> 90922 `); 90923} 90924/** 90925 * Internal-only NgModule that works as a host for the `RadioControlRegistry` tree-shakable 90926 * provider. Note: the `InternalFormsSharedModule` can not be used here directly, since it's 90927 * declared *after* the `RadioControlRegistry` class and the `providedIn` doesn't support 90928 * `forwardRef` logic. 90929 */ 90930 90931 90932class RadioControlRegistryModule {} 90933 90934RadioControlRegistryModule.ɵfac = function RadioControlRegistryModule_Factory(t) { 90935 return new (t || RadioControlRegistryModule)(); 90936}; 90937 90938RadioControlRegistryModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({ 90939 type: RadioControlRegistryModule 90940}); 90941RadioControlRegistryModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({}); 90942 90943(function () { 90944 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RadioControlRegistryModule, [{ 90945 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule 90946 }], null, null); 90947})(); 90948/** 90949 * @description 90950 * Class used by Angular to track radio buttons. For internal use only. 90951 */ 90952 90953 90954class RadioControlRegistry { 90955 constructor() { 90956 this._accessors = []; 90957 } 90958 /** 90959 * @description 90960 * Adds a control to the internal registry. For internal use only. 90961 */ 90962 90963 90964 add(control, accessor) {
90965 this._accessors.push([control, accessor]); 90966 } 90967 /** 90968 * @description 90969 * Removes a control from the internal registry. For internal use only. 90970 */ 90971 90972 90973 remove(accessor) { 90974 for (let i = this._accessors.length - 1; i >= 0; --i) { 90975 if (this._accessors[i][1] === accessor) { 90976 this._accessors.splice(i, 1); 90977 90978 return; 90979 } 90980 } 90981 } 90982 /** 90983 * @description 90984 * Selects a radio button. For internal use only. 90985 */ 90986 90987 90988 select(accessor) { 90989 this._accessors.forEach(c => { 90990 if (this._isSameGroup(c, accessor) && c[1] !== accessor) { 90991 c[1].fireUncheck(accessor.value); 90992 } 90993 }); 90994 } 90995 90996 _isSameGroup(controlPair, accessor) { 90997 if (!controlPair[0].control) return false; 90998 return controlPair[0]._parent === accessor._control._parent && controlPair[1].name === accessor.name; 90999 } 91000 91001} 91002 91003RadioControlRegistry.ɵfac = function RadioControlRegistry_Factory(t) { 91004 return new (t || RadioControlRegistry)(); 91005}; 91006 91007RadioControlRegistry.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 91008 token: RadioControlRegistry, 91009 factory: RadioControlRegistry.ɵfac, 91010 providedIn: RadioControlRegistryModule 91011}); 91012 91013(function () { 91014 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RadioControlRegistry, [{ 91015 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 91016 args: [{ 91017 providedIn: RadioControlRegistryModule 91018 }] 91019 }], null, null); 91020})(); 91021/** 91022 * @description 91023 * The `ControlValueAccessor` for writing radio control values and listening to radio control 91024 * changes. The value accessor is used by the `FormControlDirective`, `FormControlName`, and 91025 * `NgModel` directives. 91026 * 91027 * @usageNotes 91028 * 91029 * ### Using radio buttons with reactive form directives 91030 * 91031 * The follow example shows how to use radio buttons in a reactive form. When using radio buttons in 91032 * a reactive form, radio buttons in the same group should have the same `formControlName`. 91033 * Providing a `name` attribute is optional. 91034 * 91035 * {@example forms/ts/reactiveRadioButtons/reactive_radio_button_example.ts region='Reactive'} 91036 * 91037 * @ngModule ReactiveFormsModule 91038 * @ngModule FormsModule 91039 * @publicApi 91040 */ 91041 91042 91043class RadioControlValueAccessor extends BuiltInControlValueAccessor { 91044 constructor(renderer, elementRef, _registry, _injector) { 91045 super(renderer, elementRef); 91046 this._registry = _registry; 91047 this._injector = _injector; 91048 /** 91049 * The registered callback function called when a change event occurs on the input element. 91050 * Note: we declare `onChange` here (also used as host listener) as a function with no arguments 91051 * to override the `onChange` function (which expects 1 argument) in the parent 91052 * `BaseControlValueAccessor` class. 91053 * @nodoc 91054 */ 91055 91056 this.onChange = () => {}; 91057 } 91058 /** @nodoc */ 91059 91060 91061 ngOnInit() { 91062 this._control = this._injector.get(NgControl); 91063 91064 this._checkName(); 91065 91066 this._registry.add(this._control, this); 91067 } 91068 /** @nodoc */ 91069 91070 91071 ngOnDestroy() { 91072 this._registry.remove(this); 91073 } 91074 /** 91075 * Sets the "checked" property value on the radio input element. 91076 * @nodoc 91077 */ 91078 91079 91080 writeValue(value) { 91081 this._state = value === this.value; 91082 this.setProperty('checked', this._state); 91083 } 91084 /** 91085 * Registers a function called when the control value changes. 91086 * @nodoc 91087 */ 91088 91089 91090 registerOnChange(fn) { 91091 this._fn = fn; 91092 91093 this.onChange = () => { 91094 fn(this.value); 91095 91096 this._registry.select(this); 91097 }; 91098 } 91099 /** 91100 * Sets the "value" on the radio input element and unchecks it. 91101 * 91102 * @param value 91103 */ 91104 91105 91106 fireUncheck(value) { 91107 this.writeValue(value); 91108 } 91109 91110 _checkName() { 91111 if (this.name && this.formControlName && this.name !== this.formControlName && (typeof ngDevMode === 'undefined' || ngDevMode)) { 91112 throwNameError(); 91113 } 91114 91115 if (!this.name && this.formControlName) this.name = this.formControlName; 91116 } 91117 91118} 91119 91120RadioControlValueAccessor.ɵfac = function RadioControlValueAccessor_Factory(t) { 91121 return new (t || RadioControlValueAccessor)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](RadioControlRegistry), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector)); 91122}; 91123 91124RadioControlValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 91125 type: RadioControlValueAccessor, 91126 selectors: [["input", "type", "radio", "formControlName", ""], ["input", "type", "radio", "formControl", ""], ["input", "type", "radio", "ngModel", ""]], 91127 hostBindings: function RadioControlValueAccessor_HostBindings(rf, ctx) { 91128 if (rf & 1) { 91129 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("change", function RadioControlValueAccessor_change_HostBindingHandler() { 91130 return ctx.onChange(); 91131 })("blur", function RadioControlValueAccessor_blur_HostBindingHandler() { 91132 return ctx.onTouched(); 91133 }); 91134 } 91135 }, 91136 inputs: { 91137 name: "name", 91138 formControlName: "formControlName", 91139 value: "value" 91140 }, 91141 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([RADIO_VALUE_ACCESSOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 91142}); 91143 91144(function () { 91145 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RadioControlValueAccessor, [{ 91146 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 91147 args: [{ 91148 selector: 'input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]', 91149 host: { 91150 '(change)': 'onChange()', 91151 '(blur)': 'onTouched()' 91152 }, 91153 providers: [RADIO_VALUE_ACCESSOR] 91154 }] 91155 }], function () { 91156 return [{ 91157 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2 91158 }, {
91159 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef 91160 }, { 91161 type: RadioControlRegistry 91162 }, { 91163 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector 91164 }]; 91165 }, { 91166 name: [{ 91167 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 91168 }], 91169 formControlName: [{ 91170 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 91171 }], 91172 value: [{ 91173 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 91174 }] 91175 }); 91176})(); 91177/** 91178 * @license 91179 * Copyright Google LLC All Rights Reserved. 91180 * 91181 * Use of this source code is governed by an MIT-style license that can be 91182 * found in the LICENSE file at https://angular.io/license 91183 */ 91184 91185 91186const RANGE_VALUE_ACCESSOR = { 91187 provide: NG_VALUE_ACCESSOR, 91188 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => RangeValueAccessor), 91189 multi: true 91190}; 91191/** 91192 * @description 91193 * The `ControlValueAccessor` for writing a range value and listening to range input changes. 91194 * The value accessor is used by the `FormControlDirective`, `FormControlName`, and `NgModel` 91195 * directives. 91196 * 91197 * @usageNotes 91198 * 91199 * ### Using a range input with a reactive form 91200 * 91201 * The following example shows how to use a range input with a reactive form. 91202 * 91203 * ```ts 91204 * const ageControl = new FormControl(); 91205 * ``` 91206 * 91207 * ``` 91208 * <input type="range" [formControl]="ageControl"> 91209 * ``` 91210 * 91211 * @ngModule ReactiveFormsModule 91212 * @ngModule FormsModule 91213 * @publicApi 91214 */ 91215 91216class RangeValueAccessor extends BuiltInControlValueAccessor { 91217 /** 91218 * Sets the "value" property on the input element. 91219 * @nodoc 91220 */ 91221 writeValue(value) { 91222 this.setProperty('value', parseFloat(value)); 91223 } 91224 /** 91225 * Registers a function called when the control value changes. 91226 * @nodoc 91227 */ 91228 91229 91230 registerOnChange(fn) { 91231 this.onChange = value => { 91232 fn(value == '' ? null : parseFloat(value)); 91233 }; 91234 } 91235 91236} 91237 91238RangeValueAccessor.ɵfac = /* @__PURE__ */function () { 91239 let ɵRangeValueAccessor_BaseFactory; 91240 return function RangeValueAccessor_Factory(t) { 91241 return (ɵRangeValueAccessor_BaseFactory || (ɵRangeValueAccessor_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](RangeValueAccessor)))(t || RangeValueAccessor); 91242 }; 91243}(); 91244 91245RangeValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 91246 type: RangeValueAccessor, 91247 selectors: [["input", "type", "range", "formControlName", ""], ["input", "type", "range", "formControl", ""], ["input", "type", "range", "ngModel", ""]], 91248 hostBindings: function RangeValueAccessor_HostBindings(rf, ctx) { 91249 if (rf & 1) { 91250 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("change", function RangeValueAccessor_change_HostBindingHandler($event) { 91251 return ctx.onChange($event.target.value); 91252 })("input", function RangeValueAccessor_input_HostBindingHandler($event) { 91253 return ctx.onChange($event.target.value); 91254 })("blur", function RangeValueAccessor_blur_HostBindingHandler() { 91255 return ctx.onTouched(); 91256 }); 91257 } 91258 }, 91259 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([RANGE_VALUE_ACCESSOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 91260}); 91261 91262(function () { 91263 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RangeValueAccessor, [{ 91264 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 91265 args: [{ 91266 selector: 'input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]', 91267 host: { 91268 '(change)': 'onChange($event.target.value)', 91269 '(input)': 'onChange($event.target.value)', 91270 '(blur)': 'onTouched()' 91271 }, 91272 providers: [RANGE_VALUE_ACCESSOR] 91273 }] 91274 }], null, null); 91275})(); 91276/** 91277 * @license 91278 * Copyright Google LLC All Rights Reserved. 91279 * 91280 * Use of this source code is governed by an MIT-style license that can be 91281 * found in the LICENSE file at https://angular.io/license 91282 */ 91283 91284/** 91285 * Token to provide to turn off the ngModel warning on formControl and formControlName. 91286 */ 91287 91288 91289const NG_MODEL_WITH_FORM_CONTROL_WARNING = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('NgModelWithFormControlWarning'); 91290const formControlBinding = { 91291 provide: NgControl, 91292 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => FormControlDirective) 91293}; 91294/** 91295 * @description 91296 * Synchronizes a standalone `FormControl` instance to a form control element. 91297 *
91298 * Note that support for using the `ngModel` input property and `ngModelChange` event with reactive 91299 * form directives was deprecated in Angular v6 and is scheduled for removal in 91300 * a future version of Angular. 91301 * For details, see [Deprecated features](guide/deprecations#ngmodel-with-reactive-forms). 91302 * 91303 * @see [Reactive Forms Guide](guide/reactive-forms) 91304 * @see `FormControl` 91305 * @see `AbstractControl` 91306 * 91307 * @usageNotes 91308 * 91309 * The following example shows how to register a standalone control and set its value. 91310 * 91311 * {@example forms/ts/simpleFormControl/simple_form_control_example.ts region='Component'} 91312 * 91313 * @ngModule ReactiveFormsModule 91314 * @publicApi 91315 */ 91316 91317class FormControlDirective extends NgControl { 91318 constructor(validators, asyncValidators, valueAccessors, _ngModelWarningConfig) { 91319 super(); 91320 this._ngModelWarningConfig = _ngModelWarningConfig; 91321 /** @deprecated as of v6 */ 91322 91323 this.update = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); 91324 /** 91325 * @description 91326 * Instance property used to track whether an ngModel warning has been sent out for this 91327 * particular `FormControlDirective` instance. Used to support warning config of "always". 91328 * 91329 * @internal 91330 */ 91331 91332 this._ngModelWarningSent = false; 91333 91334 this._setValidators(validators); 91335 91336 this._setAsyncValidators(asyncValidators); 91337 91338 this.valueAccessor = selectValueAccessor(this, valueAccessors); 91339 } 91340 /** 91341 * @description 91342 * Triggers a warning in dev mode that this input should not be used with reactive forms. 91343 */ 91344 91345 91346 set isDisabled(isDisabled) { 91347 if (typeof ngDevMode === 'undefined' || ngDevMode) { 91348 console.warn(disabledAttrWarning); 91349 } 91350 } 91351 /** @nodoc */ 91352 91353 91354 ngOnChanges(changes) { 91355 if (this._isControlChanged(changes)) { 91356 const previousForm = changes['form'].previousValue; 91357 91358 if (previousForm) { 91359 cleanUpControl(previousForm, this, 91360 /* validateControlPresenceOnChange */ 91361 false); 91362 } 91363 91364 setUpControl(this.form, this); 91365 this.form.updateValueAndValidity({ 91366 emitEvent: false 91367 }); 91368 } 91369 91370 if (isPropertyUpdated(changes, this.viewModel)) { 91371 if (typeof ngDevMode === 'undefined' || ngDevMode) { 91372 _ngModelWarning('formControl', FormControlDirective, this, this._ngModelWarningConfig); 91373 } 91374 91375 this.form.setValue(this.model); 91376 this.viewModel = this.model; 91377 } 91378 } 91379 /** @nodoc */ 91380 91381 91382 ngOnDestroy() { 91383 if (this.form) { 91384 cleanUpControl(this.form, this, 91385 /* validateControlPresenceOnChange */ 91386 false); 91387 } 91388 } 91389 /** 91390 * @description 91391 * Returns an array that represents the path from the top-level form to this control. 91392 * Each index is the string name of the control on that level. 91393 */ 91394 91395 91396 get path() { 91397 return []; 91398 } 91399 /** 91400 * @description 91401 * The `FormControl` bound to this directive. 91402 */ 91403 91404 91405 get control() { 91406 return this.form; 91407 } 91408 /** 91409 * @description 91410 * Sets the new value for the view model and emits an `ngModelChange` event. 91411 * 91412 * @param newValue The new value for the view model. 91413 */ 91414 91415 91416 viewToModelUpdate(newValue) { 91417 this.viewModel = newValue; 91418 this.update.emit(newValue); 91419 } 91420 91421 _isControlChanged(changes) { 91422 return changes.hasOwnProperty('form'); 91423 } 91424 91425} 91426/** 91427 * @description 91428 * Static property used to track whether any ngModel warnings have been sent across 91429 * all instances of FormControlDirective. Used to support warning config of "once". 91430 * 91431 * @internal 91432 */ 91433 91434 91435FormControlDirective._ngModelWarningSentOnce = false; 91436 91437FormControlDirective.ɵfac = function FormControlDirective_Factory(t) { 91438 return new (t || FormControlDirective)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALUE_ACCESSOR, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_MODEL_WITH_FORM_CONTROL_WARNING, 8)); 91439}; 91440 91441FormControlDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 91442 type: FormControlDirective, 91443 selectors: [["", "formControl", ""]], 91444 inputs: { 91445 form: ["formControl", "form"], 91446 isDisabled: ["disabled", "isDisabled"], 91447 model: ["ngModel", "model"] 91448 }, 91449 outputs: { 91450 update: "ngModelChange" 91451 }, 91452 exportAs: ["ngForm"], 91453 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([formControlBinding]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"], _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]] 91454}); 91455 91456(function () { 91457 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FormControlDirective, [{ 91458 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 91459 args: [{ 91460 selector: '[formControl]', 91461 providers: [formControlBinding], 91462 exportAs: 'ngForm' 91463 }] 91464 }], function () { 91465 return [{ 91466 type: undefined, 91467 decorators: [{ 91468 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 91469 }, { 91470 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 91471 }, { 91472 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 91473 args: [NG_VALIDATORS] 91474 }] 91475 }, {
91476 type: undefined, 91477 decorators: [{ 91478 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 91479 }, { 91480 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 91481 }, { 91482 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 91483 args: [NG_ASYNC_VALIDATORS] 91484 }] 91485 }, { 91486 type: undefined, 91487 decorators: [{ 91488 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 91489 }, { 91490 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 91491 }, { 91492 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 91493 args: [NG_VALUE_ACCESSOR] 91494 }] 91495 }, { 91496 type: undefined, 91497 decorators: [{ 91498 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 91499 }, { 91500 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 91501 args: [NG_MODEL_WITH_FORM_CONTROL_WARNING] 91502 }] 91503 }]; 91504 }, { 91505 form: [{ 91506 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 91507 args: ['formControl'] 91508 }], 91509 isDisabled: [{ 91510 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 91511 args: ['disabled'] 91512 }], 91513 model: [{ 91514 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 91515 args: ['ngModel'] 91516 }], 91517 update: [{ 91518 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output, 91519 args: ['ngModelChange'] 91520 }] 91521 }); 91522})(); 91523/** 91524 * @license 91525 * Copyright Google LLC All Rights Reserved. 91526 * 91527 * Use of this source code is governed by an MIT-style license that can be 91528 * found in the LICENSE file at https://angular.io/license 91529 */ 91530 91531 91532const formDirectiveProvider = { 91533 provide: ControlContainer, 91534 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => FormGroupDirective) 91535}; 91536/** 91537 * @description 91538 * 91539 * Binds an existing `FormGroup` or `FormRecord` to a DOM element. 91540 * 91541 * This directive accepts an existing `FormGroup` instance. It will then use this 91542 * `FormGroup` instance to match any child `FormControl`, `FormGroup`/`FormRecord`, 91543 * and `FormArray` instances to child `FormControlName`, `FormGroupName`, 91544 * and `FormArrayName` directives. 91545 * 91546 * @see [Reactive Forms Guide](guide/reactive-forms) 91547 * @see `AbstractControl` 91548 * 91549 * @usageNotes 91550 * ### Register Form Group 91551 * 91552 * The following example registers a `FormGroup` with first name and last name controls, 91553 * and listens for the *ngSubmit* event when the button is clicked. 91554 * 91555 * {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'} 91556 * 91557 * @ngModule ReactiveFormsModule 91558 * @publicApi 91559 */ 91560 91561class FormGroupDirective extends ControlContainer { 91562 constructor(validators, asyncValidators) { 91563 super(); 91564 /** 91565 * @description 91566 * Reports whether the form submission has been triggered. 91567 */ 91568 91569 this.submitted = false; 91570 /** 91571 * Callback that should be invoked when controls in FormGroup or FormArray collection change 91572 * (added or removed). This callback triggers corresponding DOM updates. 91573 */ 91574 91575 this._onCollectionChange = () => this._updateDomValue(); 91576 /** 91577 * @description 91578 * Tracks the list of added `FormControlName` instances 91579 */ 91580 91581 91582 this.directives = []; 91583 /** 91584 * @description 91585 * Tracks the `FormGroup` bound to this directive. 91586 */ 91587 91588 this.form = null; 91589 /** 91590 * @description 91591 * Emits an event when the form submission has been triggered. 91592 */ 91593 91594 this.ngSubmit = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); 91595 91596 this._setValidators(validators); 91597 91598 this._setAsyncValidators(asyncValidators); 91599 } 91600 /** @nodoc */ 91601 91602 91603 ngOnChanges(changes) { 91604 this._checkFormPresent(); 91605 91606 if (changes.hasOwnProperty('form')) { 91607 this._updateValidators(); 91608 91609 this._updateDomValue(); 91610 91611 this._updateRegistrations(); 91612 91613 this._oldForm = this.form; 91614 } 91615 } 91616 /** @nodoc */ 91617 91618 91619 ngOnDestroy() { 91620 if (this.form) { 91621 cleanUpValidators(this.form, this); // Currently the `onCollectionChange` callback is rewritten each time the 91622 // `_registerOnCollectionChange` function is invoked. The implication is that cleanup should
vendor: 4,847 bytes, lines 91623-91817
91623 // happen *only* when the `onCollectionChange` callback was set by this directive instance. 91624 // Otherwise it might cause overriding a callback of some other directive instances. We should 91625 // consider updating this logic later to make it similar to how `onChange` callbacks are 91626 // handled, see https://github.com/angular/angular/issues/39732 for additional info. 91627 91628 if (this.form._onCollectionChange === this._onCollectionChange) { 91629 this.form._registerOnCollectionChange(() => {}); 91630 } 91631 } 91632 } 91633 /** 91634 * @description 91635 * Returns this directive's instance. 91636 */ 91637 91638 91639 get formDirective() { 91640 return this; 91641 } 91642 /** 91643 * @description 91644 * Returns the `FormGroup` bound to this directive. 91645 */ 91646 91647 91648 get control() { 91649 return this.form; 91650 } 91651 /** 91652 * @description 91653 * Returns an array representing the path to this group. Because this directive 91654 * always lives at the top level of a form, it always an empty array. 91655 */ 91656 91657 91658 get path() { 91659 return []; 91660 } 91661 /** 91662 * @description 91663 * Method that sets up the control directive in this group, re-calculates its value 91664 * and validity, and adds the instance to the internal list of directives. 91665 * 91666 * @param dir The `FormControlName` directive instance. 91667 */ 91668 91669 91670 addControl(dir) { 91671 const ctrl = this.form.get(dir.path); 91672 setUpControl(ctrl, dir); 91673 ctrl.updateValueAndValidity({ 91674 emitEvent: false 91675 }); 91676 this.directives.push(dir); 91677 return ctrl; 91678 } 91679 /** 91680 * @description 91681 * Retrieves the `FormControl` instance from the provided `FormControlName` directive 91682 * 91683 * @param dir The `FormControlName` directive instance. 91684 */ 91685 91686 91687 getControl(dir) { 91688 return this.form.get(dir.path); 91689 } 91690 /** 91691 * @description 91692 * Removes the `FormControlName` instance from the internal list of directives 91693 * 91694 * @param dir The `FormControlName` directive instance. 91695 */ 91696 91697 91698 removeControl(dir) { 91699 cleanUpControl(dir.control || null, dir, 91700 /* validateControlPresenceOnChange */ 91701 false); 91702 removeListItem$1(this.directives, dir); 91703 } 91704 /** 91705 * Adds a new `FormGroupName` directive instance to the form. 91706 * 91707 * @param dir The `FormGroupName` directive instance. 91708 */ 91709 91710 91711 addFormGroup(dir) { 91712 this._setUpFormContainer(dir); 91713 } 91714 /** 91715 * Performs the necessary cleanup when a `FormGroupName` directive instance is removed from the 91716 * view. 91717 * 91718 * @param dir The `FormGroupName` directive instance. 91719 */ 91720 91721 91722 removeFormGroup(dir) { 91723 this._cleanUpFormContainer(dir); 91724 } 91725 /** 91726 * @description 91727 * Retrieves the `FormGroup` for a provided `FormGroupName` directive instance 91728 * 91729 * @param dir The `FormGroupName` directive instance. 91730 */ 91731 91732 91733 getFormGroup(dir) { 91734 return this.form.get(dir.path); 91735 } 91736 /** 91737 * Performs the necessary setup when a `FormArrayName` directive instance is added to the view. 91738 * 91739 * @param dir The `FormArrayName` directive instance. 91740 */ 91741 91742 91743 addFormArray(dir) { 91744 this._setUpFormContainer(dir); 91745 } 91746 /** 91747 * Performs the necessary cleanup when a `FormArrayName` directive instance is removed from the 91748 * view. 91749 * 91750 * @param dir The `FormArrayName` directive instance. 91751 */ 91752 91753 91754 removeFormArray(dir) { 91755 this._cleanUpFormContainer(dir); 91756 } 91757 /** 91758 * @description 91759 * Retrieves the `FormArray` for a provided `FormArrayName` directive instance. 91760 * 91761 * @param dir The `FormArrayName` directive instance. 91762 */ 91763 91764 91765 getFormArray(dir) { 91766 return this.form.get(dir.path); 91767 } 91768 /** 91769 * Sets the new value for the provided `FormControlName` directive. 91770 * 91771 * @param dir The `FormControlName` directive instance. 91772 * @param value The new value for the directive's control. 91773 */ 91774 91775 91776 updateModel(dir, value) { 91777 const ctrl = this.form.get(dir.path); 91778 ctrl.setValue(value); 91779 } 91780 /** 91781 * @description 91782 * Method called with the "submit" event is triggered on the form. 91783 * Triggers the `ngSubmit` emitter to emit the "submit" event as its payload. 91784 * 91785 * @param $event The "submit" event object 91786 */ 91787 91788 91789 onSubmit($event) { 91790 this.submitted = true; 91791 syncPendingControls(this.form, this.directives); 91792 this.ngSubmit.emit($event); // Forms with `method="dialog"` have some special behavior that won't reload the page and that 91793 // shouldn't be prevented. Note that we need to null check the `event` and the `target`, because 91794 // some internal apps call this method directly with the wrong arguments. 91795 91796 return $event?.target?.method === 'dialog'; 91797 } 91798 /** 91799 * @description 91800 * Method called when the "reset" event is triggered on the form. 91801 */ 91802 91803 91804 onReset() { 91805 this.resetForm(); 91806 } 91807 /** 91808 * @description 91809 * Resets the form to an initial value and resets its submitted status. 91810 * 91811 * @param value The new value for the form. 91812 */ 91813 91814 91815 resetForm(value = undefined) { 91816 this.form.reset(value); 91817 this.submitted = false;
91818 } 91819 /** @internal */ 91820 91821 91822 _updateDomValue() { 91823 this.directives.forEach(dir => { 91824 const oldCtrl = dir.control; 91825 const newCtrl = this.form.get(dir.path); 91826 91827 if (oldCtrl !== newCtrl) { 91828 // Note: the value of the `dir.control` may not be defined, for example when it's a first 91829 // `FormControl` that is added to a `FormGroup` instance (via `addControl` call). 91830 cleanUpControl(oldCtrl || null, dir); // Check whether new control at the same location inside the corresponding `FormGroup` is an 91831 // instance of `FormControl` and perform control setup only if that's the case. 91832 // Note: we don't need to clear the list of directives (`this.directives`) here, it would be 91833 // taken care of in the `removeControl` method invoked when corresponding `formControlName` 91834 // directive instance is being removed (invoked from `FormControlName.ngOnDestroy`). 91835 91836 if (isFormControl(newCtrl)) { 91837 setUpControl(newCtrl, dir); 91838 dir.control = newCtrl; 91839 } 91840 } 91841 }); 91842 91843 this.form._updateTreeValidity({ 91844 emitEvent: false 91845 }); 91846 } 91847 91848 _setUpFormContainer(dir) { 91849 const ctrl = this.form.get(dir.path); 91850 setUpFormContainer(ctrl, dir); // NOTE: this operation looks unnecessary in case no new validators were added in 91851 // `setUpFormContainer` call. Consider updating this code to match the logic in 91852 // `_cleanUpFormContainer` function. 91853 91854 ctrl.updateValueAndValidity({ 91855 emitEvent: false 91856 }); 91857 } 91858 91859 _cleanUpFormContainer(dir) { 91860 if (this.form) { 91861 const ctrl = this.form.get(dir.path); 91862 91863 if (ctrl) { 91864 const isControlUpdated = cleanUpFormContainer(ctrl, dir); 91865 91866 if (isControlUpdated) { 91867 // Run validity check only in case a control was updated (i.e. view validators were 91868 // removed) as removing view validators might cause validity to change. 91869 ctrl.updateValueAndValidity({ 91870 emitEvent: false 91871 }); 91872 } 91873 } 91874 } 91875 } 91876 91877 _updateRegistrations() { 91878 this.form._registerOnCollectionChange(this._onCollectionChange); 91879 91880 if (this._oldForm) { 91881 this._oldForm._registerOnCollectionChange(() => {}); 91882 } 91883 } 91884 91885 _updateValidators() { 91886 setUpValidators(this.form, this); 91887 91888 if (this._oldForm) { 91889 cleanUpValidators(this._oldForm, this); 91890 } 91891 } 91892 91893 _checkFormPresent() { 91894 if (!this.form && (typeof ngDevMode === 'undefined' || ngDevMode)) { 91895 throw missingFormException(); 91896 } 91897 } 91898 91899} 91900 91901FormGroupDirective.ɵfac = function FormGroupDirective_Factory(t) { 91902 return new (t || FormGroupDirective)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10)); 91903}; 91904 91905FormGroupDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 91906 type: FormGroupDirective, 91907 selectors: [["", "formGroup", ""]], 91908 hostBindings: function FormGroupDirective_HostBindings(rf, ctx) { 91909 if (rf & 1) { 91910 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("submit", function FormGroupDirective_submit_HostBindingHandler($event) { 91911 return ctx.onSubmit($event); 91912 })("reset", function FormGroupDirective_reset_HostBindingHandler() { 91913 return ctx.onReset(); 91914 }); 91915 } 91916 }, 91917 inputs: { 91918 form: ["formGroup", "form"] 91919 }, 91920 outputs: { 91921 ngSubmit: "ngSubmit" 91922 }, 91923 exportAs: ["ngForm"], 91924 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([formDirectiveProvider]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"], _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]] 91925}); 91926 91927(function () { 91928 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FormGroupDirective, [{ 91929 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 91930 args: [{ 91931 selector: '[formGroup]', 91932 providers: [formDirectiveProvider], 91933 host: { 91934 '(submit)': 'onSubmit($event)', 91935 '(reset)': 'onReset()'
91936 }, 91937 exportAs: 'ngForm' 91938 }] 91939 }], function () { 91940 return [{ 91941 type: undefined, 91942 decorators: [{ 91943 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 91944 }, { 91945 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 91946 }, { 91947 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 91948 args: [NG_VALIDATORS] 91949 }] 91950 }, { 91951 type: undefined, 91952 decorators: [{ 91953 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 91954 }, { 91955 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 91956 }, { 91957 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 91958 args: [NG_ASYNC_VALIDATORS] 91959 }] 91960 }]; 91961 }, { 91962 form: [{ 91963 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 91964 args: ['formGroup'] 91965 }], 91966 ngSubmit: [{ 91967 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output 91968 }] 91969 }); 91970})(); 91971/** 91972 * @license 91973 * Copyright Google LLC All Rights Reserved. 91974 * 91975 * Use of this source code is governed by an MIT-style license that can be 91976 * found in the LICENSE file at https://angular.io/license 91977 */ 91978 91979 91980const formGroupNameProvider = { 91981 provide: ControlContainer, 91982 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => FormGroupName) 91983}; 91984/** 91985 * @description 91986 * 91987 * Syncs a nested `FormGroup` or `FormRecord` to a DOM element. 91988 * 91989 * This directive can only be used with a parent `FormGroupDirective`. 91990 * 91991 * It accepts the string name of the nested `FormGroup` or `FormRecord` to link, and 91992 * looks for a `FormGroup` or `FormRecord` registered with that name in the parent 91993 * `FormGroup` instance you passed into `FormGroupDirective`. 91994 * 91995 * Use nested form groups to validate a sub-group of a 91996 * form separately from the rest or to group the values of certain 91997 * controls into their own nested object. 91998 * 91999 * @see [Reactive Forms Guide](guide/reactive-forms) 92000 * 92001 * @usageNotes 92002 * 92003 * ### Access the group by name 92004 * 92005 * The following example uses the `AbstractControl.get` method to access the 92006 * associated `FormGroup` 92007 * 92008 * ```ts 92009 * this.form.get('name'); 92010 * ``` 92011 * 92012 * ### Access individual controls in the group 92013 * 92014 * The following example uses the `AbstractControl.get` method to access 92015 * individual controls within the group using dot syntax. 92016 * 92017 * ```ts 92018 * this.form.get('name.first'); 92019 * ``` 92020 * 92021 * ### Register a nested `FormGroup`. 92022 * 92023 * The following example registers a nested *name* `FormGroup` within an existing `FormGroup`, 92024 * and provides methods to retrieve the nested `FormGroup` and individual controls. 92025 * 92026 * {@example forms/ts/nestedFormGroup/nested_form_group_example.ts region='Component'} 92027 * 92028 * @ngModule ReactiveFormsModule 92029 * @publicApi 92030 */ 92031 92032class FormGroupName extends AbstractFormGroupDirective { 92033 constructor(parent, validators, asyncValidators) { 92034 super(); 92035 this._parent = parent; 92036 92037 this._setValidators(validators); 92038 92039 this._setAsyncValidators(asyncValidators); 92040 } 92041 /** @internal */ 92042 92043 92044 _checkParentType() { 92045 if (_hasInvalidParent(this._parent) && (typeof ngDevMode === 'undefined' || ngDevMode)) { 92046 throw groupParentException(); 92047 } 92048 } 92049 92050} 92051 92052FormGroupName.ɵfac = function FormGroupName_Factory(t) { 92053 return new (t || FormGroupName)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ControlContainer, 13), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10)); 92054}; 92055 92056FormGroupName.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 92057 type: FormGroupName, 92058 selectors: [["", "formGroupName", ""]], 92059 inputs: { 92060 name: ["formGroupName", "name"] 92061 }, 92062 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([formGroupNameProvider]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 92063}); 92064 92065(function () { 92066 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FormGroupName, [{ 92067 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 92068 args: [{ 92069 selector: '[formGroupName]', 92070 providers: [formGroupNameProvider] 92071 }] 92072 }], function () { 92073 return [{ 92074 type: ControlContainer, 92075 decorators: [{ 92076 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 92077 }, { 92078 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host 92079 }, { 92080 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.SkipSelf 92081 }] 92082 }, {
92083 type: undefined, 92084 decorators: [{ 92085 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 92086 }, { 92087 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 92088 }, { 92089 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 92090 args: [NG_VALIDATORS] 92091 }] 92092 }, { 92093 type: undefined, 92094 decorators: [{ 92095 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 92096 }, { 92097 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 92098 }, { 92099 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 92100 args: [NG_ASYNC_VALIDATORS] 92101 }] 92102 }]; 92103 }, { 92104 name: [{ 92105 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 92106 args: ['formGroupName'] 92107 }] 92108 }); 92109})(); 92110 92111const formArrayNameProvider = { 92112 provide: ControlContainer, 92113 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => FormArrayName) 92114}; 92115/** 92116 * @description 92117 * 92118 * Syncs a nested `FormArray` to a DOM element. 92119 * 92120 * This directive is designed to be used with a parent `FormGroupDirective` (selector: 92121 * `[formGroup]`). 92122 * 92123 * It accepts the string name of the nested `FormArray` you want to link, and 92124 * will look for a `FormArray` registered with that name in the parent 92125 * `FormGroup` instance you passed into `FormGroupDirective`. 92126 * 92127 * @see [Reactive Forms Guide](guide/reactive-forms) 92128 * @see `AbstractControl` 92129 * 92130 * @usageNotes 92131 * 92132 * ### Example 92133 * 92134 * {@example forms/ts/nestedFormArray/nested_form_array_example.ts region='Component'} 92135 * 92136 * @ngModule ReactiveFormsModule 92137 * @publicApi 92138 */ 92139 92140class FormArrayName extends ControlContainer { 92141 constructor(parent, validators, asyncValidators) { 92142 super(); 92143 this._parent = parent; 92144 92145 this._setValidators(validators); 92146 92147 this._setAsyncValidators(asyncValidators); 92148 } 92149 /** 92150 * A lifecycle method called when the directive's inputs are initialized. For internal use only. 92151 * @throws If the directive does not have a valid parent. 92152 * @nodoc 92153 */ 92154 92155 92156 ngOnInit() { 92157 this._checkParentType(); 92158 92159 this.formDirective.addFormArray(this); 92160 } 92161 /** 92162 * A lifecycle method called before the directive's instance is destroyed. For internal use only. 92163 * @nodoc 92164 */ 92165 92166 92167 ngOnDestroy() { 92168 if (this.formDirective) { 92169 this.formDirective.removeFormArray(this); 92170 } 92171 } 92172 /** 92173 * @description 92174 * The `FormArray` bound to this directive. 92175 */ 92176 92177 92178 get control() { 92179 return this.formDirective.getFormArray(this); 92180 } 92181 /** 92182 * @description 92183 * The top-level directive for this group if present, otherwise null. 92184 */ 92185 92186 92187 get formDirective() { 92188 return this._parent ? this._parent.formDirective : null; 92189 } 92190 /** 92191 * @description 92192 * Returns an array that represents the path from the top-level form to this control. 92193 * Each index is the string name of the control on that level. 92194 */ 92195 92196 92197 get path() { 92198 return controlPath(this.name == null ? this.name : this.name.toString(), this._parent); 92199 } 92200 92201 _checkParentType() { 92202 if (_hasInvalidParent(this._parent) && (typeof ngDevMode === 'undefined' || ngDevMode)) { 92203 throw arrayParentException(); 92204 } 92205 } 92206 92207} 92208 92209FormArrayName.ɵfac = function FormArrayName_Factory(t) { 92210 return new (t || FormArrayName)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ControlContainer, 13), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10)); 92211}; 92212 92213FormArrayName.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 92214 type: FormArrayName, 92215 selectors: [["", "formArrayName", ""]], 92216 inputs: { 92217 name: ["formArrayName", "name"] 92218 }, 92219 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([formArrayNameProvider]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 92220}); 92221 92222(function () { 92223 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FormArrayName, [{ 92224 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 92225 args: [{ 92226 selector: '[formArrayName]', 92227 providers: [formArrayNameProvider] 92228 }] 92229 }], function () { 92230 return [{ 92231 type: ControlContainer, 92232 decorators: [{ 92233 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 92234 }, { 92235 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host 92236 }, { 92237 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.SkipSelf 92238 }] 92239 }, {
92240 type: undefined, 92241 decorators: [{ 92242 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 92243 }, { 92244 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 92245 }, { 92246 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 92247 args: [NG_VALIDATORS] 92248 }] 92249 }, { 92250 type: undefined, 92251 decorators: [{ 92252 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 92253 }, { 92254 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 92255 }, { 92256 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 92257 args: [NG_ASYNC_VALIDATORS] 92258 }] 92259 }]; 92260 }, { 92261 name: [{ 92262 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 92263 args: ['formArrayName'] 92264 }] 92265 }); 92266})(); 92267 92268function _hasInvalidParent(parent) { 92269 return !(parent instanceof FormGroupName) && !(parent instanceof FormGroupDirective) && !(parent instanceof FormArrayName); 92270} 92271/** 92272 * @license 92273 * Copyright Google LLC All Rights Reserved. 92274 * 92275 * Use of this source code is governed by an MIT-style license that can be 92276 * found in the LICENSE file at https://angular.io/license 92277 */ 92278 92279 92280const controlNameBinding = { 92281 provide: NgControl, 92282 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => FormControlName) 92283}; 92284/** 92285 * @description 92286 * Syncs a `FormControl` in an existing `FormGroup` to a form control 92287 * element by name. 92288 * 92289 * @see [Reactive Forms Guide](guide/reactive-forms) 92290 * @see `FormControl` 92291 * @see `AbstractControl` 92292 * 92293 * @usageNotes 92294 * 92295 * ### Register `FormControl` within a group 92296 * 92297 * The following example shows how to register multiple form controls within a form group 92298 * and set their value. 92299 * 92300 * {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'} 92301 * 92302 * To see `formControlName` examples with different form control types, see: 92303 * 92304 * * Radio buttons: `RadioControlValueAccessor` 92305 * * Selects: `SelectControlValueAccessor` 92306 * 92307 * ### Use with ngModel is deprecated 92308 * 92309 * Support for using the `ngModel` input property and `ngModelChange` event with reactive 92310 * form directives has been deprecated in Angular v6 and is scheduled for removal in 92311 * a future version of Angular. 92312 * 92313 * For details, see [Deprecated features](guide/deprecations#ngmodel-with-reactive-forms). 92314 * 92315 * @ngModule ReactiveFormsModule 92316 * @publicApi 92317 */ 92318 92319class FormControlName extends NgControl { 92320 constructor(parent, validators, asyncValidators, valueAccessors, _ngModelWarningConfig) { 92321 super(); 92322 this._ngModelWarningConfig = _ngModelWarningConfig; 92323 this._added = false; 92324 /** @deprecated as of v6 */ 92325 92326 this.update = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); 92327 /** 92328 * @description 92329 * Instance property used to track whether an ngModel warning has been sent out for this 92330 * particular FormControlName instance. Used to support warning config of "always". 92331 * 92332 * @internal 92333 */ 92334 92335 this._ngModelWarningSent = false; 92336 this._parent = parent; 92337 92338 this._setValidators(validators); 92339 92340 this._setAsyncValidators(asyncValidators); 92341 92342 this.valueAccessor = selectValueAccessor(this, valueAccessors); 92343 } 92344 /** 92345 * @description 92346 * Triggers a warning in dev mode that this input should not be used with reactive forms. 92347 */ 92348 92349 92350 set isDisabled(isDisabled) { 92351 if (typeof ngDevMode === 'undefined' || ngDevMode) { 92352 console.warn(disabledAttrWarning); 92353 } 92354 } 92355 /** @nodoc */ 92356 92357 92358 ngOnChanges(changes) { 92359 if (!this._added) this._setUpControl(); 92360 92361 if (isPropertyUpdated(changes, this.viewModel)) { 92362 if (typeof ngDevMode === 'undefined' || ngDevMode) { 92363 _ngModelWarning('formControlName', FormControlName, this, this._ngModelWarningConfig); 92364 } 92365 92366 this.viewModel = this.model; 92367 this.formDirective.updateModel(this, this.model); 92368 } 92369 } 92370 /** @nodoc */ 92371 92372 92373 ngOnDestroy() { 92374 if (this.formDirective) { 92375 this.formDirective.removeControl(this); 92376 } 92377 } 92378 /** 92379 * @description 92380 * Sets the new value for the view model and emits an `ngModelChange` event. 92381 * 92382 * @param newValue The new value for the view model. 92383 */ 92384 92385 92386 viewToModelUpdate(newValue) { 92387 this.viewModel = newValue; 92388 this.update.emit(newValue); 92389 } 92390 /** 92391 * @description 92392 * Returns an array that represents the path from the top-level form to this control. 92393 * Each index is the string name of the control on that level. 92394 */ 92395 92396 92397 get path() { 92398 return controlPath(this.name == null ? this.name : this.name.toString(), this._parent); 92399 } 92400 /** 92401 * @description 92402 * The top-level directive for this group if present, otherwise null. 92403 */ 92404 92405 92406 get formDirective() { 92407 return this._parent ? this._parent.formDirective : null; 92408 } 92409 92410 _checkParentType() { 92411 if (typeof ngDevMode === 'undefined' || ngDevMode) { 92412 if (!(this._parent instanceof FormGroupName) && this._parent instanceof AbstractFormGroupDirective) { 92413 throw ngModelGroupException(); 92414 } else if (!(this._parent instanceof FormGroupName) && !(this._parent instanceof FormGroupDirective) && !(this._parent instanceof FormArrayName)) { 92415 throw controlParentException(); 92416 } 92417 } 92418 } 92419 92420 _setUpControl() { 92421 this._checkParentType(); 92422 92423 this.control = this.formDirective.addControl(this); 92424 this._added = true; 92425 } 92426 92427} 92428/** 92429 * @description 92430 * Static property used to track whether any ngModel warnings have been sent across 92431 * all instances of FormControlName. Used to support warning config of "once". 92432 * 92433 * @internal 92434 */ 92435 92436 92437FormControlName._ngModelWarningSentOnce = false;
92438 92439FormControlName.ɵfac = function FormControlName_Factory(t) { 92440 return new (t || FormControlName)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ControlContainer, 13), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_ASYNC_VALIDATORS, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_VALUE_ACCESSOR, 10), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NG_MODEL_WITH_FORM_CONTROL_WARNING, 8)); 92441}; 92442 92443FormControlName.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 92444 type: FormControlName, 92445 selectors: [["", "formControlName", ""]], 92446 inputs: { 92447 name: ["formControlName", "name"], 92448 isDisabled: ["disabled", "isDisabled"], 92449 model: ["ngModel", "model"] 92450 }, 92451 outputs: { 92452 update: "ngModelChange" 92453 }, 92454 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([controlNameBinding]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"], _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]] 92455}); 92456 92457(function () { 92458 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FormControlName, [{ 92459 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 92460 args: [{ 92461 selector: '[formControlName]', 92462 providers: [controlNameBinding] 92463 }] 92464 }], function () { 92465 return [{ 92466 type: ControlContainer, 92467 decorators: [{ 92468 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 92469 }, { 92470 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host 92471 }, { 92472 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.SkipSelf 92473 }] 92474 }, { 92475 type: undefined, 92476 decorators: [{ 92477 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 92478 }, { 92479 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 92480 }, { 92481 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 92482 args: [NG_VALIDATORS] 92483 }] 92484 }, { 92485 type: undefined, 92486 decorators: [{ 92487 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 92488 }, { 92489 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 92490 }, { 92491 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 92492 args: [NG_ASYNC_VALIDATORS] 92493 }] 92494 }, { 92495 type: undefined, 92496 decorators: [{ 92497 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 92498 }, { 92499 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Self 92500 }, { 92501 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 92502 args: [NG_VALUE_ACCESSOR] 92503 }] 92504 }, { 92505 type: undefined, 92506 decorators: [{ 92507 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 92508 }, { 92509 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 92510 args: [NG_MODEL_WITH_FORM_CONTROL_WARNING] 92511 }] 92512 }]; 92513 }, { 92514 name: [{ 92515 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 92516 args: ['formControlName'] 92517 }], 92518 isDisabled: [{ 92519 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 92520 args: ['disabled'] 92521 }], 92522 model: [{ 92523 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 92524 args: ['ngModel'] 92525 }], 92526 update: [{ 92527 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output, 92528 args: ['ngModelChange'] 92529 }] 92530 }); 92531})(); 92532/** 92533 * @license 92534 * Copyright Google LLC All Rights Reserved. 92535 * 92536 * Use of this source code is governed by an MIT-style license that can be 92537 * found in the LICENSE file at https://angular.io/license 92538 */ 92539 92540 92541const SELECT_VALUE_ACCESSOR = { 92542 provide: NG_VALUE_ACCESSOR, 92543 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => SelectControlValueAccessor), 92544 multi: true 92545}; 92546 92547function _buildValueString$1(id, value) { 92548 if (id == null) return `${value}`; 92549 if (value && typeof value === 'object') value = 'Object'; 92550 return `${id}: ${value}`.slice(0, 50); 92551} 92552 92553function _extractId$1(valueString) { 92554 return valueString.split(':')[0]; 92555} 92556/** 92557 * @description 92558 * The `ControlValueAccessor` for writing select control values and listening to select control 92559 * changes. The value accessor is used by the `FormControlDirective`, `FormControlName`, and 92560 * `NgModel` directives. 92561 * 92562 * @usageNotes 92563 * 92564 * ### Using select controls in a reactive form 92565 * 92566 * The following examples show how to use a select control in a reactive form. 92567 * 92568 * {@example forms/ts/reactiveSelectControl/reactive_select_control_example.ts region='Component'} 92569 * 92570 * ### Using select controls in a template-driven form 92571 * 92572 * To use a select in a template-driven form, simply add an `ngModel` and a `name` 92573 * attribute to the main `<select>` tag. 92574 * 92575 * {@example forms/ts/selectControl/select_control_example.ts region='Component'} 92576 * 92577 * ### Customizing option selection 92578 * 92579 * Angular uses object identity to select option. It's possible for the identities of items 92580 * to change while the data does not. This can happen, for example, if the items are produced
92581 * from an RPC to the server, and that RPC is re-run. Even if the data hasn't changed, the 92582 * second response will produce objects with different identities. 92583 * 92584 * To customize the default option comparison algorithm, `<select>` supports `compareWith` input. 92585 * `compareWith` takes a **function** which has two arguments: `option1` and `option2`. 92586 * If `compareWith` is given, Angular selects option by the return value of the function. 92587 * 92588 * ```ts 92589 * const selectedCountriesControl = new FormControl(); 92590 * ``` 92591 * 92592 * ``` 92593 * <select [compareWith]="compareFn" [formControl]="selectedCountriesControl"> 92594 * <option *ngFor="let country of countries" [ngValue]="country"> 92595 * {{country.name}} 92596 * </option> 92597 * </select> 92598 * 92599 * compareFn(c1: Country, c2: Country): boolean { 92600 * return c1 && c2 ? c1.id === c2.id : c1 === c2; 92601 * } 92602 * ``` 92603 * 92604 * **Note:** We listen to the 'change' event because 'input' events aren't fired 92605 * for selects in IE, see: 92606 * https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event#browser_compatibility 92607 * 92608 * @ngModule ReactiveFormsModule 92609 * @ngModule FormsModule 92610 * @publicApi 92611 */ 92612 92613 92614class SelectControlValueAccessor extends BuiltInControlValueAccessor { 92615 constructor() { 92616 super(...arguments); 92617 /** @internal */ 92618 92619 this._optionMap = new Map(); 92620 /** @internal */ 92621 92622 this._idCounter = 0; 92623 this._compareWith = Object.is; 92624 } 92625 /** 92626 * @description 92627 * Tracks the option comparison algorithm for tracking identities when 92628 * checking for changes. 92629 */ 92630 92631 92632 set compareWith(fn) { 92633 if (typeof fn !== 'function' && (typeof ngDevMode === 'undefined' || ngDevMode)) { 92634 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1201 92635 /* RuntimeErrorCode.COMPAREWITH_NOT_A_FN */ 92636 , `compareWith must be a function, but received ${JSON.stringify(fn)}`); 92637 } 92638 92639 this._compareWith = fn; 92640 } 92641 /** 92642 * Sets the "value" property on the select element. 92643 * @nodoc 92644 */ 92645 92646 92647 writeValue(value) { 92648 this.value = value; 92649 92650 const id = this._getOptionId(value); 92651 92652 const valueString = _buildValueString$1(id, value); 92653 92654 this.setProperty('value', valueString); 92655 } 92656 /** 92657 * Registers a function called when the control value changes. 92658 * @nodoc 92659 */ 92660 92661 92662 registerOnChange(fn) { 92663 this.onChange = valueString => { 92664 this.value = this._getOptionValue(valueString); 92665 fn(this.value); 92666 }; 92667 } 92668 /** @internal */ 92669 92670 92671 _registerOption() { 92672 return (this._idCounter++).toString(); 92673 } 92674 /** @internal */ 92675 92676 92677 _getOptionId(value) { 92678 for (const id of Array.from(this._optionMap.keys())) { 92679 if (this._compareWith(this._optionMap.get(id), value)) return id; 92680 } 92681 92682 return null; 92683 } 92684 /** @internal */ 92685 92686 92687 _getOptionValue(valueString) { 92688 const id = _extractId$1(valueString); 92689 92690 return this._optionMap.has(id) ? this._optionMap.get(id) : valueString; 92691 } 92692 92693} 92694 92695SelectControlValueAccessor.ɵfac = /* @__PURE__ */function () { 92696 let ɵSelectControlValueAccessor_BaseFactory; 92697 return function SelectControlValueAccessor_Factory(t) { 92698 return (ɵSelectControlValueAccessor_BaseFactory || (ɵSelectControlValueAccessor_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](SelectControlValueAccessor)))(t || SelectControlValueAccessor); 92699 }; 92700}(); 92701 92702SelectControlValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 92703 type: SelectControlValueAccessor, 92704 selectors: [["select", "formControlName", "", 3, "multiple", ""], ["select", "formControl", "", 3, "multiple", ""], ["select", "ngModel", "", 3, "multiple", ""]], 92705 hostBindings: function SelectControlValueAccessor_HostBindings(rf, ctx) { 92706 if (rf & 1) { 92707 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("change", function SelectControlValueAccessor_change_HostBindingHandler($event) { 92708 return ctx.onChange($event.target.value); 92709 })("blur", function SelectControlValueAccessor_blur_HostBindingHandler() { 92710 return ctx.onTouched(); 92711 }); 92712 } 92713 }, 92714 inputs: { 92715 compareWith: "compareWith" 92716 }, 92717 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([SELECT_VALUE_ACCESSOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 92718}); 92719 92720(function () { 92721 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](SelectControlValueAccessor, [{ 92722 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 92723 args: [{ 92724 selector: 'select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]', 92725 host: { 92726 '(change)': 'onChange($event.target.value)', 92727 '(blur)': 'onTouched()' 92728 }, 92729 providers: [SELECT_VALUE_ACCESSOR] 92730 }] 92731 }], null, { 92732 compareWith: [{ 92733 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 92734 }] 92735 }); 92736})(); 92737/** 92738 * @description 92739 * Marks `<option>` as dynamic, so Angular can be notified when options change. 92740 * 92741 * @see `SelectControlValueAccessor` 92742 * 92743 * @ngModule ReactiveFormsModule 92744 * @ngModule FormsModule 92745 * @publicApi 92746 */ 92747 92748 92749class NgSelectOption { 92750 constructor(_element, _renderer, _select) { 92751 this._element = _element; 92752 this._renderer = _renderer; 92753 this._select = _select; 92754 if (this._select) this.id = this._select._registerOption(); 92755 } 92756 /** 92757 * @description 92758 * Tracks the value bound to the option element. Unlike the value binding, 92759 * ngValue supports binding to objects. 92760 */ 92761 92762 92763 set ngValue(value) { 92764 if (this._select == null) return; 92765 92766 this._select._optionMap.set(this.id, value); 92767 92768 this._setElementValue(_buildValueString$1(this.id, value)); 92769 92770 this._select.writeValue(this._select.value); 92771 } 92772 /** 92773 * @description 92774 * Tracks simple string values bound to the option element. 92775 * For objects, use the `ngValue` input binding. 92776 */ 92777 92778 92779 set value(value) { 92780 this._setElementValue(value); 92781 92782 if (this._select) this._select.writeValue(this._select.value); 92783 } 92784 /** @internal */ 92785 92786 92787 _setElementValue(value) { 92788 this._renderer.setProperty(this._element.nativeElement, 'value', value); 92789 } 92790 /** @nodoc */ 92791 92792 92793 ngOnDestroy() { 92794 if (this._select) {
92795 this._select._optionMap.delete(this.id); 92796 92797 this._select.writeValue(this._select.value); 92798 } 92799 } 92800 92801} 92802 92803NgSelectOption.ɵfac = function NgSelectOption_Factory(t) { 92804 return new (t || NgSelectOption)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](SelectControlValueAccessor, 9)); 92805}; 92806 92807NgSelectOption.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 92808 type: NgSelectOption, 92809 selectors: [["option"]], 92810 inputs: { 92811 ngValue: "ngValue", 92812 value: "value" 92813 } 92814}); 92815 92816(function () { 92817 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgSelectOption, [{ 92818 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 92819 args: [{ 92820 selector: 'option' 92821 }] 92822 }], function () { 92823 return [{ 92824 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef 92825 }, { 92826 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2 92827 }, { 92828 type: SelectControlValueAccessor, 92829 decorators: [{ 92830 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 92831 }, { 92832 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host 92833 }] 92834 }]; 92835 }, { 92836 ngValue: [{ 92837 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 92838 args: ['ngValue'] 92839 }], 92840 value: [{ 92841 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 92842 args: ['value'] 92843 }] 92844 }); 92845})(); 92846/** 92847 * @license 92848 * Copyright Google LLC All Rights Reserved. 92849 * 92850 * Use of this source code is governed by an MIT-style license that can be 92851 * found in the LICENSE file at https://angular.io/license 92852 */ 92853 92854 92855const SELECT_MULTIPLE_VALUE_ACCESSOR = { 92856 provide: NG_VALUE_ACCESSOR, 92857 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => SelectMultipleControlValueAccessor), 92858 multi: true 92859}; 92860 92861function _buildValueString(id, value) { 92862 if (id == null) return `${value}`; 92863 if (typeof value === 'string') value = `'${value}'`; 92864 if (value && typeof value === 'object') value = 'Object'; 92865 return `${id}: ${value}`.slice(0, 50); 92866} 92867 92868function _extractId(valueString) { 92869 return valueString.split(':')[0]; 92870} 92871/** Mock interface for HTMLCollection */ 92872 92873 92874class HTMLCollection {} 92875/** 92876 * @description 92877 * The `ControlValueAccessor` for writing multi-select control values and listening to multi-select 92878 * control changes. The value accessor is used by the `FormControlDirective`, `FormControlName`, and 92879 * `NgModel` directives. 92880 * 92881 * @see `SelectControlValueAccessor` 92882 * 92883 * @usageNotes 92884 * 92885 * ### Using a multi-select control 92886 * 92887 * The follow example shows you how to use a multi-select control with a reactive form. 92888 * 92889 * ```ts 92890 * const countryControl = new FormControl(); 92891 * ``` 92892 * 92893 * ``` 92894 * <select multiple name="countries" [formControl]="countryControl"> 92895 * <option *ngFor="let country of countries" [ngValue]="country"> 92896 * {{ country.name }} 92897 * </option> 92898 * </select> 92899 * ``` 92900 * 92901 * ### Customizing option selection 92902 * 92903 * To customize the default option comparison algorithm, `<select>` supports `compareWith` input. 92904 * See the `SelectControlValueAccessor` for usage. 92905 * 92906 * @ngModule ReactiveFormsModule 92907 * @ngModule FormsModule 92908 * @publicApi 92909 */ 92910 92911 92912class SelectMultipleControlValueAccessor extends BuiltInControlValueAccessor { 92913 constructor() { 92914 super(...arguments); 92915 /** @internal */ 92916 92917 this._optionMap = new Map(); 92918 /** @internal */ 92919 92920 this._idCounter = 0; 92921 this._compareWith = Object.is; 92922 } 92923 /** 92924 * @description 92925 * Tracks the option comparison algorithm for tracking identities when 92926 * checking for changes. 92927 */ 92928 92929 92930 set compareWith(fn) { 92931 if (typeof fn !== 'function' && (typeof ngDevMode === 'undefined' || ngDevMode)) { 92932 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](1201 92933 /* RuntimeErrorCode.COMPAREWITH_NOT_A_FN */ 92934 , `compareWith must be a function, but received ${JSON.stringify(fn)}`); 92935 } 92936 92937 this._compareWith = fn; 92938 } 92939 /** 92940 * Sets the "value" property on one or of more of the select's options. 92941 * @nodoc 92942 */ 92943 92944 92945 writeValue(value) { 92946 this.value = value; 92947 let optionSelectedStateSetter; 92948 92949 if (Array.isArray(value)) { 92950 // convert values to ids 92951 const ids = value.map(v => this._getOptionId(v)); 92952 92953 optionSelectedStateSetter = (opt, o) => { 92954 opt._setSelected(ids.indexOf(o.toString()) > -1); 92955 }; 92956 } else { 92957 optionSelectedStateSetter = (opt, o) => { 92958 opt._setSelected(false); 92959 }; 92960 } 92961
92962 this._optionMap.forEach(optionSelectedStateSetter); 92963 } 92964 /** 92965 * Registers a function called when the control value changes 92966 * and writes an array of the selected options. 92967 * @nodoc 92968 */ 92969 92970 92971 registerOnChange(fn) { 92972 this.onChange = element => { 92973 const selected = []; 92974 const selectedOptions = element.selectedOptions; 92975 92976 if (selectedOptions !== undefined) { 92977 const options = selectedOptions; 92978 92979 for (let i = 0; i < options.length; i++) { 92980 const opt = options[i]; 92981 92982 const val = this._getOptionValue(opt.value); 92983 92984 selected.push(val); 92985 } 92986 } // Degrade to use `options` when `selectedOptions` property is not available. 92987 // Note: the `selectedOptions` is available in all supported browsers, but the Domino lib 92988 // doesn't have it currently, see https://github.com/fgnass/domino/issues/177. 92989 else { 92990 const options = element.options; 92991 92992 for (let i = 0; i < options.length; i++) { 92993 const opt = options[i]; 92994 92995 if (opt.selected) { 92996 const val = this._getOptionValue(opt.value); 92997 92998 selected.push(val); 92999 } 93000 } 93001 } 93002 93003 this.value = selected; 93004 fn(selected); 93005 }; 93006 } 93007 /** @internal */ 93008 93009 93010 _registerOption(value) { 93011 const id = (this._idCounter++).toString(); 93012 93013 this._optionMap.set(id, value); 93014 93015 return id; 93016 } 93017 /** @internal */ 93018 93019 93020 _getOptionId(value) { 93021 for (const id of Array.from(this._optionMap.keys())) { 93022 if (this._compareWith(this._optionMap.get(id)._value, value)) return id; 93023 } 93024 93025 return null; 93026 } 93027 /** @internal */ 93028 93029 93030 _getOptionValue(valueString) { 93031 const id = _extractId(valueString); 93032 93033 return this._optionMap.has(id) ? this._optionMap.get(id)._value : valueString; 93034 } 93035 93036} 93037 93038SelectMultipleControlValueAccessor.ɵfac = /* @__PURE__ */function () { 93039 let ɵSelectMultipleControlValueAccessor_BaseFactory; 93040 return function SelectMultipleControlValueAccessor_Factory(t) { 93041 return (ɵSelectMultipleControlValueAccessor_BaseFactory || (ɵSelectMultipleControlValueAccessor_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](SelectMultipleControlValueAccessor)))(t || SelectMultipleControlValueAccessor); 93042 }; 93043}(); 93044 93045SelectMultipleControlValueAccessor.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 93046 type: SelectMultipleControlValueAccessor, 93047 selectors: [["select", "multiple", "", "formControlName", ""], ["select", "multiple", "", "formControl", ""], ["select", "multiple", "", "ngModel", ""]], 93048 hostBindings: function SelectMultipleControlValueAccessor_HostBindings(rf, ctx) { 93049 if (rf & 1) { 93050 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("change", function SelectMultipleControlValueAccessor_change_HostBindingHandler($event) { 93051 return ctx.onChange($event.target); 93052 })("blur", function SelectMultipleControlValueAccessor_blur_HostBindingHandler() { 93053 return ctx.onTouched(); 93054 }); 93055 } 93056 }, 93057 inputs: { 93058 compareWith: "compareWith" 93059 }, 93060 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([SELECT_MULTIPLE_VALUE_ACCESSOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 93061}); 93062 93063(function () { 93064 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](SelectMultipleControlValueAccessor, [{ 93065 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 93066 args: [{ 93067 selector: 'select[multiple][formControlName],select[multiple][formControl],select[multiple][ngModel]', 93068 host: { 93069 '(change)': 'onChange($event.target)', 93070 '(blur)': 'onTouched()' 93071 }, 93072 providers: [SELECT_MULTIPLE_VALUE_ACCESSOR] 93073 }] 93074 }], null, { 93075 compareWith: [{ 93076 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 93077 }] 93078 }); 93079})(); 93080/** 93081 * @description 93082 * Marks `<option>` as dynamic, so Angular can be notified when options change. 93083 * 93084 * @see `SelectMultipleControlValueAccessor` 93085 * 93086 * @ngModule ReactiveFormsModule 93087 * @ngModule FormsModule 93088 * @publicApi 93089 */ 93090 93091 93092class ɵNgSelectMultipleOption { 93093 constructor(_element, _renderer, _select) { 93094 this._element = _element; 93095 this._renderer = _renderer; 93096 this._select = _select; 93097 93098 if (this._select) { 93099 this.id = this._select._registerOption(this); 93100 } 93101 } 93102 /** 93103 * @description 93104 * Tracks the value bound to the option element. Unlike the value binding, 93105 * ngValue supports binding to objects. 93106 */ 93107 93108 93109 set ngValue(value) { 93110 if (this._select == null) return; 93111 this._value = value; 93112 93113 this._setElementValue(_buildValueString(this.id, value)); 93114 93115 this._select.writeValue(this._select.value); 93116 } 93117 /** 93118 * @description 93119 * Tracks simple string values bound to the option element. 93120 * For objects, use the `ngValue` input binding. 93121 */ 93122 93123 93124 set value(value) { 93125 if (this._select) { 93126 this._value = value; 93127 93128 this._setElementValue(_buildValueString(this.id, value)); 93129 93130 this._select.writeValue(this._select.value); 93131 } else { 93132 this._setElementValue(value); 93133 } 93134 } 93135 /** @internal */ 93136 93137 93138 _setElementValue(value) { 93139 this._renderer.setProperty(this._element.nativeElement, 'value', value); 93140 } 93141 /** @internal */ 93142 93143 93144 _setSelected(selected) { 93145 this._renderer.setProperty(this._element.nativeElement, 'selected', selected); 93146 } 93147 /** @nodoc */ 93148 93149 93150 ngOnDestroy() { 93151 if (this._select) {
93152 this._select._optionMap.delete(this.id); 93153 93154 this._select.writeValue(this._select.value); 93155 } 93156 } 93157 93158} 93159 93160ɵNgSelectMultipleOption.ɵfac = function ɵNgSelectMultipleOption_Factory(t) { 93161 return new (t || ɵNgSelectMultipleOption)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](SelectMultipleControlValueAccessor, 9)); 93162}; 93163 93164ɵNgSelectMultipleOption.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 93165 type: ɵNgSelectMultipleOption, 93166 selectors: [["option"]], 93167 inputs: { 93168 ngValue: "ngValue", 93169 value: "value" 93170 } 93171}); 93172 93173(function () { 93174 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ɵNgSelectMultipleOption, [{ 93175 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 93176 args: [{ 93177 selector: 'option' 93178 }] 93179 }], function () { 93180 return [{ 93181 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef 93182 }, { 93183 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2 93184 }, { 93185 type: SelectMultipleControlValueAccessor, 93186 decorators: [{ 93187 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 93188 }, { 93189 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Host 93190 }] 93191 }]; 93192 }, { 93193 ngValue: [{ 93194 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 93195 args: ['ngValue'] 93196 }], 93197 value: [{ 93198 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 93199 args: ['value'] 93200 }] 93201 }); 93202})(); 93203/** 93204 * @license 93205 * Copyright Google LLC All Rights Reserved. 93206 * 93207 * Use of this source code is governed by an MIT-style license that can be 93208 * found in the LICENSE file at https://angular.io/license 93209 */ 93210 93211/** 93212 * Method that updates string to integer if not already a number 93213 * 93214 * @param value The value to convert to integer. 93215 * @returns value of parameter converted to number or integer. 93216 */ 93217 93218 93219function toInteger(value) { 93220 return typeof value === 'number' ? value : parseInt(value, 10); 93221} 93222/** 93223 * Method that ensures that provided value is a float (and converts it to float if needed). 93224 * 93225 * @param value The value to convert to float. 93226 * @returns value of parameter converted to number or float. 93227 */ 93228 93229 93230function toFloat(value) { 93231 return typeof value === 'number' ? value : parseFloat(value); 93232} 93233/** 93234 * A base class for Validator-based Directives. The class contains common logic shared across such 93235 * Directives. 93236 * 93237 * For internal use only, this class is not intended for use outside of the Forms package. 93238 */ 93239 93240 93241class AbstractValidatorDirective { 93242 constructor() { 93243 this._validator = nullValidator; 93244 } 93245 /** @nodoc */ 93246 93247 93248 ngOnChanges(changes) { 93249 if (this.inputName in changes) { 93250 const input = this.normalizeInput(changes[this.inputName].currentValue); 93251 this._enabled = this.enabled(input); 93252 this._validator = this._enabled ? this.createValidator(input) : nullValidator; 93253 93254 if (this._onChange) { 93255 this._onChange(); 93256 } 93257 } 93258 } 93259 /** @nodoc */ 93260 93261 93262 validate(control) { 93263 return this._validator(control); 93264 } 93265 /** @nodoc */ 93266 93267 93268 registerOnValidatorChange(fn) { 93269 this._onChange = fn; 93270 } 93271 /** 93272 * @description 93273 * Determines whether this validator should be active or not based on an input. 93274 * Base class implementation checks whether an input is defined (if the value is different from 93275 * `null` and `undefined`). Validator classes that extend this base class can override this 93276 * function with the logic specific to a particular validator directive. 93277 */ 93278 93279 93280 enabled(input) { 93281 return input != null 93282 /* both `null` and `undefined` */ 93283 ; 93284 } 93285 93286} 93287 93288AbstractValidatorDirective.ɵfac = function AbstractValidatorDirective_Factory(t) { 93289 return new (t || AbstractValidatorDirective)(); 93290}; 93291 93292AbstractValidatorDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 93293 type: AbstractValidatorDirective, 93294 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]] 93295}); 93296 93297(function () { 93298 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](AbstractValidatorDirective, [{ 93299 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive 93300 }], null, null); 93301})(); 93302/** 93303 * @description 93304 * Provider which adds `MaxValidator` to the `NG_VALIDATORS` multi-provider list. 93305 */ 93306 93307 93308const MAX_VALIDATOR = { 93309 provide: NG_VALIDATORS, 93310 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => MaxValidator), 93311 multi: true 93312}; 93313/** 93314 * A directive which installs the {@link MaxValidator} for any `formControlName`, 93315 * `formControl`, or control with `ngModel` that also has a `max` attribute. 93316 * 93317 * @see [Form Validation](guide/form-validation) 93318 * 93319 * @usageNotes 93320 * 93321 * ### Adding a max validator 93322 * 93323 * The following example shows how to add a max validator to an input attached to an 93324 * ngModel binding. 93325 * 93326 * ```html 93327 * <input type="number" ngModel max="4"> 93328 * ``` 93329 * 93330 * @ngModule ReactiveFormsModule 93331 * @ngModule FormsModule 93332 * @publicApi 93333 */ 93334 93335class MaxValidator extends AbstractValidatorDirective { 93336 constructor() { 93337 super(...arguments); 93338 /** @internal */ 93339 93340 this.inputName = 'max'; 93341 /** @internal */ 93342 93343 this.normalizeInput = input => toFloat(input); 93344 /** @internal */ 93345 93346 93347 this.createValidator = max => maxValidator(max); 93348 } 93349 93350} 93351 93352MaxValidator.ɵfac = /* @__PURE__ */function () { 93353 let ɵMaxValidator_BaseFactory; 93354 return function MaxValidator_Factory(t) { 93355 return (ɵMaxValidator_BaseFactory || (ɵMaxValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](MaxValidator)))(t || MaxValidator); 93356 }; 93357}(); 93358 93359MaxValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 93360 type: MaxValidator, 93361 selectors: [["input", "type", "number", "max", "", "formControlName", ""], ["input", "type", "number", "max", "", "formControl", ""], ["input", "type", "number", "max", "", "ngModel", ""]], 93362 hostVars: 1, 93363 hostBindings: function MaxValidator_HostBindings(rf, ctx) { 93364 if (rf & 2) { 93365 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("max", ctx._enabled ? ctx.max : null); 93366 } 93367 }, 93368 inputs: { 93369 max: "max" 93370 }, 93371 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([MAX_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 93372}); 93373 93374(function () { 93375 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](MaxValidator, [{ 93376 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 93377 args: [{ 93378 selector: 'input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]', 93379 providers: [MAX_VALIDATOR], 93380 host: { 93381 '[attr.max]': '_enabled ? max : null' 93382 } 93383 }] 93384 }], null, { 93385 max: [{ 93386 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 93387 }] 93388 }); 93389})(); 93390/** 93391 * @description 93392 * Provider which adds `MinValidator` to the `NG_VALIDATORS` multi-provider list. 93393 */ 93394 93395 93396const MIN_VALIDATOR = { 93397 provide: NG_VALIDATORS, 93398 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => MinValidator), 93399 multi: true 93400}; 93401/** 93402 * A directive which installs the {@link MinValidator} for any `formControlName`, 93403 * `formControl`, or control with `ngModel` that also has a `min` attribute. 93404 * 93405 * @see [Form Validation](guide/form-validation) 93406 * 93407 * @usageNotes 93408 * 93409 * ### Adding a min validator 93410 * 93411 * The following example shows how to add a min validator to an input attached to an 93412 * ngModel binding. 93413 * 93414 * ```html 93415 * <input type="number" ngModel min="4"> 93416 * ``` 93417 * 93418 * @ngModule ReactiveFormsModule 93419 * @ngModule FormsModule 93420 * @publicApi 93421 */ 93422 93423class MinValidator extends AbstractValidatorDirective { 93424 constructor() { 93425 super(...arguments); 93426 /** @internal */ 93427 93428 this.inputName = 'min'; 93429 /** @internal */ 93430 93431 this.normalizeInput = input => toFloat(input); 93432 /** @internal */ 93433 93434 93435 this.createValidator = min => minValidator(min); 93436 } 93437 93438} 93439 93440MinValidator.ɵfac = /* @__PURE__ */function () { 93441 let ɵMinValidator_BaseFactory; 93442 return function MinValidator_Factory(t) { 93443 return (ɵMinValidator_BaseFactory || (ɵMinValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](MinValidator)))(t || MinValidator); 93444 }; 93445}(); 93446 93447MinValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 93448 type: MinValidator, 93449 selectors: [["input", "type", "number", "min", "", "formControlName", ""], ["input", "type", "number", "min", "", "formControl", ""], ["input", "type", "number", "min", "", "ngModel", ""]], 93450 hostVars: 1, 93451 hostBindings: function MinValidator_HostBindings(rf, ctx) { 93452 if (rf & 2) { 93453 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("min", ctx._enabled ? ctx.min : null); 93454 } 93455 }, 93456 inputs: { 93457 min: "min" 93458 }, 93459 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([MIN_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 93460}); 93461 93462(function () { 93463 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](MinValidator, [{ 93464 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 93465 args: [{ 93466 selector: 'input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]', 93467 providers: [MIN_VALIDATOR], 93468 host: { 93469 '[attr.min]': '_enabled ? min : null' 93470 } 93471 }] 93472 }], null, { 93473 min: [{ 93474 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 93475 }] 93476 }); 93477})(); 93478/** 93479 * @description 93480 * Provider which adds `RequiredValidator` to the `NG_VALIDATORS` multi-provider list. 93481 */ 93482 93483 93484const REQUIRED_VALIDATOR = { 93485 provide: NG_VALIDATORS, 93486 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => RequiredValidator), 93487 multi: true 93488}; 93489/** 93490 * @description 93491 * Provider which adds `CheckboxRequiredValidator` to the `NG_VALIDATORS` multi-provider list. 93492 */ 93493 93494const CHECKBOX_REQUIRED_VALIDATOR = { 93495 provide: NG_VALIDATORS, 93496 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => CheckboxRequiredValidator), 93497 multi: true 93498}; 93499/** 93500 * @description 93501 * A directive that adds the `required` validator to any controls marked with the 93502 * `required` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list. 93503 * 93504 * @see [Form Validation](guide/form-validation) 93505 * 93506 * @usageNotes 93507 * 93508 * ### Adding a required validator using template-driven forms 93509 * 93510 * ``` 93511 * <input name="fullName" ngModel required> 93512 * ``` 93513 * 93514 * @ngModule FormsModule 93515 * @ngModule ReactiveFormsModule 93516 * @publicApi 93517 */ 93518 93519class RequiredValidator extends AbstractValidatorDirective { 93520 constructor() { 93521 super(...arguments); 93522 /** @internal */ 93523 93524 this.inputName = 'required'; 93525 /** @internal */ 93526 93527 this.normalizeInput = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"]; 93528 /** @internal */ 93529 93530 this.createValidator = input => requiredValidator; 93531 } 93532 /** @nodoc */ 93533 93534 93535 enabled(input) { 93536 return input; 93537 } 93538 93539} 93540 93541RequiredValidator.ɵfac = /* @__PURE__ */function () { 93542 let ɵRequiredValidator_BaseFactory; 93543 return function RequiredValidator_Factory(t) { 93544 return (ɵRequiredValidator_BaseFactory || (ɵRequiredValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](RequiredValidator)))(t || RequiredValidator); 93545 }; 93546}(); 93547 93548RequiredValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 93549 type: RequiredValidator, 93550 selectors: [["", "required", "", "formControlName", "", 3, "type", "checkbox"], ["", "required", "", "formControl", "", 3, "type", "checkbox"], ["", "required", "", "ngModel", "", 3, "type", "checkbox"]], 93551 hostVars: 1, 93552 hostBindings: function RequiredValidator_HostBindings(rf, ctx) { 93553 if (rf & 2) { 93554 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("required", ctx._enabled ? "" : null); 93555 } 93556 }, 93557 inputs: { 93558 required: "required" 93559 }, 93560 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([REQUIRED_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 93561}); 93562 93563(function () { 93564 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RequiredValidator, [{ 93565 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 93566 args: [{ 93567 selector: ':not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]', 93568 providers: [REQUIRED_VALIDATOR], 93569 host: { 93570 '[attr.required]': '_enabled ? "" : null' 93571 } 93572 }] 93573 }], null, { 93574 required: [{ 93575 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 93576 }] 93577 }); 93578})(); 93579/** 93580 * A Directive that adds the `required` validator to checkbox controls marked with the 93581 * `required` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list. 93582 * 93583 * @see [Form Validation](guide/form-validation) 93584 * 93585 * @usageNotes 93586 * 93587 * ### Adding a required checkbox validator using template-driven forms 93588 * 93589 * The following example shows how to add a checkbox required validator to an input attached to an 93590 * ngModel binding. 93591 * 93592 * ``` 93593 * <input type="checkbox" name="active" ngModel required> 93594 * ``` 93595 * 93596 * @publicApi 93597 * @ngModule FormsModule 93598 * @ngModule ReactiveFormsModule 93599 */ 93600 93601 93602class CheckboxRequiredValidator extends RequiredValidator { 93603 constructor() { 93604 super(...arguments); 93605 /** @internal */ 93606 93607 this.createValidator = input => requiredTrueValidator; 93608 } 93609 93610} 93611 93612CheckboxRequiredValidator.ɵfac = /* @__PURE__ */function () { 93613 let ɵCheckboxRequiredValidator_BaseFactory; 93614 return function CheckboxRequiredValidator_Factory(t) { 93615 return (ɵCheckboxRequiredValidator_BaseFactory || (ɵCheckboxRequiredValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](CheckboxRequiredValidator)))(t || CheckboxRequiredValidator); 93616 }; 93617}(); 93618 93619CheckboxRequiredValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 93620 type: CheckboxRequiredValidator, 93621 selectors: [["input", "type", "checkbox", "required", "", "formControlName", ""], ["input", "type", "checkbox", "required", "", "formControl", ""], ["input", "type", "checkbox", "required", "", "ngModel", ""]], 93622 hostVars: 1, 93623 hostBindings: function CheckboxRequiredValidator_HostBindings(rf, ctx) { 93624 if (rf & 2) { 93625 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("required", ctx._enabled ? "" : null); 93626 } 93627 }, 93628 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([CHECKBOX_REQUIRED_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 93629}); 93630 93631(function () { 93632 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](CheckboxRequiredValidator, [{ 93633 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 93634 args: [{ 93635 selector: 'input[type=checkbox][required][formControlName],input[type=checkbox][required][formControl],input[type=checkbox][required][ngModel]', 93636 providers: [CHECKBOX_REQUIRED_VALIDATOR], 93637 host: { 93638 '[attr.required]': '_enabled ? "" : null' 93639 } 93640 }] 93641 }], null, null); 93642})(); 93643/** 93644 * @description 93645 * Provider which adds `EmailValidator` to the `NG_VALIDATORS` multi-provider list. 93646 */ 93647 93648 93649const EMAIL_VALIDATOR = { 93650 provide: NG_VALIDATORS, 93651 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => EmailValidator), 93652 multi: true 93653}; 93654/** 93655 * A directive that adds the `email` validator to controls marked with the 93656 * `email` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list. 93657 * 93658 * The email validation is based on the WHATWG HTML specification with some enhancements to 93659 * incorporate more RFC rules. More information can be found on the [Validators.email 93660 * page](api/forms/Validators#email). 93661 * 93662 * @see [Form Valid
93662ation](guide/form-validation) 93663 * 93664 * @usageNotes 93665 * 93666 * ### Adding an email validator 93667 * 93668 * The following example shows how to add an email validator to an input attached to an ngModel 93669 * binding. 93670 * 93671 * ``` 93672 * <input type="email" name="email" ngModel email> 93673 * <input type="email" name="email" ngModel email="true"> 93674 * <input type="email" name="email" ngModel [email]="true"> 93675 * ``` 93676 * 93677 * @publicApi 93678 * @ngModule FormsModule 93679 * @ngModule ReactiveFormsModule 93680 */ 93681 93682class EmailValidator extends AbstractValidatorDirective { 93683 constructor() { 93684 super(...arguments); 93685 /** @internal */ 93686 93687 this.inputName = 'email'; 93688 /** @internal */ 93689 93690 this.normalizeInput = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"]; 93691 /** @internal */ 93692 93693 this.createValidator = input => emailValidator; 93694 } 93695 /** @nodoc */ 93696 93697 93698 enabled(input) { 93699 return input; 93700 } 93701 93702} 93703 93704EmailValidator.ɵfac = /* @__PURE__ */function () { 93705 let ɵEmailValidator_BaseFactory; 93706 return function EmailValidator_Factory(t) { 93707 return (ɵEmailValidator_BaseFactory || (ɵEmailValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](EmailValidator)))(t || EmailValidator); 93708 }; 93709}(); 93710 93711EmailValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 93712 type: EmailValidator, 93713 selectors: [["", "email", "", "formControlName", ""], ["", "email", "", "formControl", ""], ["", "email", "", "ngModel", ""]], 93714 inputs: { 93715 email: "email" 93716 }, 93717 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([EMAIL_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 93718}); 93719 93720(function () { 93721 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](EmailValidator, [{ 93722 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 93723 args: [{ 93724 selector: '[email][formControlName],[email][formControl],[email][ngModel]', 93725 providers: [EMAIL_VALIDATOR] 93726 }] 93727 }], null, { 93728 email: [{ 93729 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 93730 }] 93731 }); 93732})(); 93733/** 93734 * @description 93735 * Provider which adds `MinLengthValidator` to the `NG_VALIDATORS` multi-provider list. 93736 */ 93737 93738 93739const MIN_LENGTH_VALIDATOR = { 93740 provide: NG_VALIDATORS, 93741 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => MinLengthValidator), 93742 multi: true 93743}; 93744/** 93745 * A directive that adds minimum length validation to controls marked with the 93746 * `minlength` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list. 93747 * 93748 * @see [Form Validation](guide/form-validation) 93749 * 93750 * @usageNotes 93751 * 93752 * ### Adding a minimum length validator 93753 * 93754 * The following example shows how to add a minimum length validator to an input attached to an 93755 * ngModel binding. 93756 * 93757 * ```html 93758 * <input name="firstName" ngModel minlength="4"> 93759 * ``` 93760 * 93761 * @ngModule ReactiveFormsModule 93762 * @ngModule FormsModule 93763 * @publicApi 93764 */ 93765 93766class MinLengthValidator extends AbstractValidatorDirective { 93767 constructor() { 93768 super(...arguments); 93769 /** @internal */ 93770 93771 this.inputName = 'minlength'; 93772 /** @internal */ 93773 93774 this.normalizeInput = input => toInteger(input); 93775 /** @internal */ 93776 93777 93778 this.createValidator = minlength => minLengthValidator(minlength); 93779 } 93780 93781} 93782 93783MinLengthValidator.ɵfac = /* @__PURE__ */function () { 93784 let ɵMinLengthValidator_BaseFactory; 93785 return function MinLengthValidator_Factory(t) { 93786 return (ɵMinLengthValidator_BaseFactory || (ɵMinLengthValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](MinLengthValidator)))(t || MinLengthValidator); 93787 }; 93788}(); 93789 93790MinLengthValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 93791 type: MinLengthValidator, 93792 selectors: [["", "minlength", "", "formControlName", ""], ["", "minlength", "", "formControl", ""], ["", "minlength", "", "ngModel", ""]], 93793 hostVars: 1, 93794 hostBindings: function MinLengthValidator_HostBindings(rf, ctx) { 93795 if (rf & 2) { 93796 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("minlength", ctx._enabled ? ctx.minlength : null); 93797 } 93798 }, 93799 inputs: { 93800 minlength: "minlength" 93801 }, 93802 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([MIN_LENGTH_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 93803}); 93804 93805(function () { 93806 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](MinLengthValidator, [{ 93807 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 93808 args: [{ 93809 selector: '[minlength][formControlName],[minlength][formControl],[minlength][ngModel]', 93810 providers: [MIN_LENGTH_VALIDATOR], 93811 host: { 93812 '[attr.minlength]': '_enabled ? minlength : null' 93813 } 93814 }] 93815 }], null, { 93816 minlength: [{ 93817 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 93818 }] 93819 }); 93820})(); 93821/** 93822 * @description 93823 * Provider which adds `MaxLengthValidator` to the `NG_VALIDATORS` multi-provider list. 93824 */ 93825 93826 93827const MAX_LENGTH_VALIDATOR = { 93828 provide: NG_VALIDATORS, 93829 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => MaxLengthValidator), 93830 multi: true 93831}; 93832/** 93833 * A directive that adds max length validation to controls marked with the 93834 * `maxlength` attribute. The directive is provided with the `NG_VALIDATORS` multi-provider list. 93835 * 93836 * @see [Form Validation](guide/form-validation) 93837 * 93838 * @usageNotes 93839 * 93840 * ### Adding a maximum length validator 93841 * 93842 * The following example shows how to add a maximum length validator to an input attached to an 93843 * ngModel binding. 93844 * 93845 * ```html 93846 * <input name="firstName" ngModel maxlength="25"> 93847 * ``` 93848 * 93849 * @ngModule ReactiveFormsModule 93850 * @ngModule FormsModule 93851 * @publicApi 93852 */ 93853 93854class MaxLengthValidator extends AbstractValidatorDirective { 93855 constructor() { 93856 super(...arguments); 93857 /** @internal */ 93858 93859 this.inputName = 'maxlength'; 93860 /** @internal */ 93861 93862 this.normalizeInput = input => toInteger(input); 93863 /** @internal */ 93864 93865 93866 this.createValidator = maxlength => maxLengthValidator(maxlength); 93867 } 93868 93869} 93870 93871MaxLengthValidator.ɵfac = /* @__PURE__ */function () { 93872 let ɵMaxLengthValidator_BaseFactory; 93873 return function MaxLengthValidator_Factory(t) { 93874 return (ɵMaxLengthValidator_BaseFactory || (ɵMaxLengthValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](MaxLengthValidator)))(t || MaxLengthValidator); 93875 }; 93876}(); 93877 93878MaxLengthValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 93879 type: MaxLengthValidator, 93880 selectors: [["", "maxlength", "", "formControlName", ""], ["", "maxlength", "", "formControl", ""], ["", "maxlength", "", "ngModel", ""]], 93881 hostVars: 1, 93882 hostBindings: function MaxLengthValidator_HostBindings(rf, ctx) { 93883 if (rf & 2) { 93884 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("maxlength", ctx._enabled ? ctx.maxlength : null); 93885 } 93886 }, 93887 inputs: { 93888 maxlength: "maxlength" 93889 }, 93890 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([MAX_LENGTH_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 93891}); 93892 93893(function () { 93894 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](MaxLengthValidator, [{ 93895 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 93896 args: [{ 93897 selector: '[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]', 93898 providers: [MAX_LENGTH_VALIDATOR], 93899 host: { 93900 '[attr.maxlength]': '_enabled ? maxlength : null' 93901 } 93902 }] 93903 }], null, { 93904 maxlength: [{ 93905 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 93906 }] 93907 }); 93908})(); 93909/** 93910 * @description 93911 * Provider which adds `PatternValidator` to the `NG_VALIDATORS` multi-provider list. 93912 */ 93913 93914 93915const PATTERN_VALIDATOR = { 93916 provide: NG_VALIDATORS, 93917 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(() => PatternValidator), 93918 multi: true 93919}; 93920/** 93921 * @description 93922 * A directive that adds regex pattern validation to controls marked with the 93923 * `pattern` attribute. The regex must match the entire control value. 93924 * The directive is provided with the `NG_VALIDATORS` multi-provider list. 93925 * 93926 * @see [Form Validation](guide/form-validation) 93927 * 93928 * @usageNotes 93929 * 93930 * ### Adding a pattern validator 93931 * 93932 * The following example shows how to add a pattern validator to an input attached to an 93933 * ngModel binding. 93934 * 93935 * ```html 93936 * <input name="firstName" ngModel pattern="[a-zA-Z ]*"> 93937 * ``` 93938 * 93939 * @ngModule ReactiveFormsModule 93940 * @ngModule FormsModule 93941 * @publicApi 93942 */ 93943 93944class PatternValidator extends AbstractValidatorDirective { 93945 constructor() { 93946 super(...arguments); 93947 /** @internal */ 93948 93949 this.inputName = 'pattern'; 93950 /** @internal */ 93951 93952 this.normalizeInput = input => input; 93953 /** @internal */ 93954 93955 93956 this.createValidator = input => patternValidator(input); 93957 } 93958 93959} 93960 93961PatternValidator.ɵfac = /* @__PURE__ */function () { 93962 let ɵPatternValidator_BaseFactory; 93963 return function PatternValidator_Factory(t) { 93964 return (ɵPatternValidator_BaseFactory || (ɵPatternValidator_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](PatternValidator)))(t || PatternValidator); 93965 }; 93966}(); 93967 93968PatternValidator.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 93969 type: PatternValidator, 93970 selectors: [["", "pattern", "", "formControlName", ""], ["", "pattern", "", "formControl", ""], ["", "pattern", "", "ngModel", ""]], 93971 hostVars: 1, 93972 hostBindings: function PatternValidator_HostBindings(rf, ctx) { 93973 if (rf & 2) { 93974 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("pattern", ctx._enabled ? ctx.pattern : null); 93975 } 93976 }, 93977 inputs: { 93978 pattern: "pattern" 93979 }, 93980 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵProvidersFeature"]([PATTERN_VALIDATOR]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵInheritDefinitionFeature"]] 93981}); 93982 93983(function () { 93984 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](PatternValidator, [{ 93985 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 93986 args: [{ 93987 selector: '[pattern][formControlName],[pattern][formControl],[pattern][ngModel]', 93988 providers: [PATTERN_VALIDATOR], 93989 host: { 93990 '[attr.pattern]': '_enabled ? pattern : null' 93991 } 93992 }] 93993 }], null, { 93994 pattern: [{ 93995 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 93996 }] 93997 }); 93998})(); 93999/** 94000 * @license 94001 * Copyright Google LLC All Rights Reserved. 94002 * 94003 * Use of this source code is governed by an MIT-style license that can be 94004 * found in the LICENSE file at https://angular.io/license 94005 */ 94006 94007 94008const SHARED_FORM_DIRECTIVES = [ɵNgNoValidate, NgSelectOption, ɵNgSelectMultipleOption, DefaultValueAccessor, NumberValueAccessor, RangeValueAccessor, CheckboxControlValueAccessor, SelectControlValueAccessor, SelectMultipleControlValueAccessor, RadioControlValueAccessor, NgControlStatus, NgControlStatusGroup, RequiredValidator, MinLengthValidator, MaxLengthValidator, PatternValidator, CheckboxRequiredValidator, EmailValidator, MinValidator, MaxValidator]; 94009const TEMPLATE_DRIVEN_DIRECTIVES = [NgModel, NgModelGroup, NgForm]; 94010const REACTIVE_DRIVEN_DIRECTIVES = [FormControlDirective, FormGroupDirective, FormControlName, FormGroupName, FormArrayName]; 94011/** 94012 * Internal module used for sharing directives between FormsModule and ReactiveFormsModule 94013 */ 94014 94015class ɵInternalFormsSharedModule {} 94016 94017ɵInternalFormsSharedModule.ɵfac = function ɵInternalFormsSharedModule_Factory(t) { 94018 return new (t || ɵInternalFormsSharedModule)(); 94019}; 94020 94021ɵInternalFormsSharedModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({ 94022 type: ɵInternalFormsSharedModule, 94023 declarations: [ɵNgNoValidate, NgSelectOption, ɵNgSelectMultipleOption, DefaultValueAccessor, NumberValueAccessor, RangeValueAccessor, CheckboxControlValueAccessor, SelectControlValueAccessor, SelectMultipleControlValueAccessor, RadioControlValueAccessor, NgControlStatus, NgControlStatusGroup, RequiredValidator, MinLengthValidator, MaxLengthValidator, PatternValidator, CheckboxRequiredValidator, EmailValidator, MinValidator, MaxValidator], 94024 imports: [RadioControlRegistryModule], 94025 exports: [ɵNgNoValidate, NgSelectOption, ɵNgSelectMultipleOption, DefaultValueAccessor, NumberValueAccessor, RangeValueAccessor, CheckboxControlValueAccessor, SelectControlValueAccessor, SelectMultipleControlValueAccessor, RadioControlValueAccessor, NgControlStatus, NgControlStatusGroup, RequiredValidator, MinLengthValidator, MaxLengthValidator, PatternValidator, CheckboxRequiredValidator, EmailValidator, MinValidator, MaxValidator] 94026}); 94027ɵInternalFormsSharedModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({ 94028 imports: [RadioControlRegistryModule] 94029}); 94030 94031(function () { 94032 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ɵInternalFormsSharedModule, [{ 94033 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule, 94034 args: [{ 94035 declarations: SHARED_FORM_DIRECTIVES, 94036 imports: [RadioControlRegistryModule], 94037 exports: SHARED_FORM_DIRECTIVES 94038 }] 94039 }], null, null); 94040})(); 94041/** 94042 * @license 94043 * Copyright Google LLC All Rights Reserved. 94044 * 94045 * Use of this source code is governed by an MIT-style license that can be 94046 * found in the LICENSE file at https://angular.io/license 94047 */ 94048 94049/** 94050 * Exports the required providers and directives for template-driven forms, 94051 * making them available for import by NgModules that import this module. 94052 * 94053 * Providers associated with this module: 94054 * * `RadioControlRegistry` 94055 * 94056 * @see [Forms Overview](/guide/forms-overview) 94057 * @see [Template-driven Forms Guide](/guide/forms) 94058 * 94059 * @publicApi 94060 */ 94061 94062 94063class FormsModule {} 94064 94065FormsModule.ɵfac = function FormsModule_Factory(t) { 94066 return new (t || FormsModule)(); 94067}; 94068 94069FormsModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({ 94070 type: FormsModule, 94071 declarations: [NgModel, NgModelGroup, NgForm], 94072 exports: [ɵInternalFormsSharedModule, NgModel, NgModelGroup, NgForm] 94073}); 94074FormsModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({ 94075 imports: [ɵInternalFormsSharedModule] 94076}); 94077 94078(function () { 94079 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FormsModule, [{ 94080 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule, 94081 args: [{ 94082 declarations: TEMPLATE_DRIVEN_DIRECTIVES, 94083 exports: [ɵInternalFormsSharedModule, TEMPLATE_DRIVEN_DIRECTIVES] 94084 }] 94085 }], null, null); 94086})(); 94087/**
94088 * Exports the required infrastructure and directives for reactive forms, 94089 * making them available for import by NgModules that import this module. 94090 * 94091 * Providers associated with this module: 94092 * * `FormBuilder` 94093 * * `RadioControlRegistry` 94094 * 94095 * @see [Forms Overview](guide/forms-overview) 94096 * @see [Reactive Forms Guide](guide/reactive-forms) 94097 * 94098 * @publicApi 94099 */ 94100 94101 94102class ReactiveFormsModule { 94103 /** 94104 * @description 94105 * Provides options for configuring the reactive forms module. 94106 * 94107 * @param opts An object of configuration options 94108 * * `warnOnNgModelWithFormControl` Configures when to emit a warning when an `ngModel` 94109 * binding is used with reactive form directives. 94110 */ 94111 static withConfig(opts) { 94112 return { 94113 ngModule: ReactiveFormsModule, 94114 providers: [{ 94115 provide: NG_MODEL_WITH_FORM_CONTROL_WARNING, 94116 useValue: opts.warnOnNgModelWithFormControl 94117 }] 94118 }; 94119 } 94120 94121} 94122 94123ReactiveFormsModule.ɵfac = function ReactiveFormsModule_Factory(t) { 94124 return new (t || ReactiveFormsModule)(); 94125}; 94126 94127ReactiveFormsModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({ 94128 type: ReactiveFormsModule,
94129 declarations: [FormControlDirective, FormGroupDirective, FormControlName, FormGroupName, FormArrayName], 94130 exports: [ɵInternalFormsSharedModule, FormControlDirective, FormGroupDirective, FormControlName, FormGroupName, FormArrayName] 94131}); 94132ReactiveFormsModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({ 94133 imports: [ɵInternalFormsSharedModule] 94134}); 94135 94136(function () { 94137 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ReactiveFormsModule, [{ 94138 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule, 94139 args: [{ 94140 declarations: [REACTIVE_DRIVEN_DIRECTIVES], 94141 exports: [ɵInternalFormsSharedModule, REACTIVE_DRIVEN_DIRECTIVES] 94142 }] 94143 }], null, null); 94144})(); 94145/** 94146 * @license 94147 * Copyright Google LLC All Rights Reserved. 94148 * 94149 * Use of this source code is governed by an MIT-style license that can be 94150 * found in the LICENSE file at https://angular.io/license 94151 */ 94152 94153/** 94154 * Tracks the value and validity state of an array of `FormControl`, 94155 * `FormGroup` or `FormArray` instances. 94156 * 94157 * A `FormArray` aggregates the values of each child `FormControl` into an array. 94158 * It calculates its status by reducing the status values of its children. For example, if one of 94159 * the controls in a `FormArray` is invalid, the entire array becomes invalid. 94160 * 94161 * `FormArray` accepts one generic argument, which is the type of the controls inside. 94162 * If you need a heterogenous array, use {@link UntypedFormArray}. 94163 * 94164 * `FormArray` is one of the four fundamental building blocks used to define forms in Angular, 94165 * along with `FormControl`, `FormGroup`, and `FormRecord`. 94166 * 94167 * @usageNotes 94168 * 94169 * ### Create an array of form controls 94170 * 94171 * ``` 94172 * const arr = new FormArray([ 94173 * new FormControl('Nancy', Validators.minLength(2)), 94174 * new FormControl('Drew'), 94175 * ]); 94176 * 94177 * console.log(arr.value); // ['Nancy', 'Drew'] 94178 * console.log(arr.status); // 'VALID' 94179 * ``` 94180 * 94181 * ### Create a form array with array-level validators 94182 * 94183 * You include array-level validators and async validators. These come in handy 94184 * when you want to perform validation that considers the value of more than one child 94185 * control. 94186 * 94187 * The two types of validators are passed in separately as the second and third arg 94188 * respectively, or together as part of an options object. 94189 * 94190 * ``` 94191 * const arr = new FormArray([ 94192 * new FormControl('Nancy'), 94193 * new FormControl('Drew') 94194 * ], {validators: myValidator, asyncValidators: myAsyncValidator}); 94195 * ``` 94196 * 94197 * ### Set the updateOn property for all controls in a form array 94198 * 94199 * The options object is used to set a default value for each child 94200 * control's `updateOn` property. If you set `updateOn` to `'blur'` at the 94201 * array level, all child controls default to 'blur', unless the child 94202 * has explicitly specified a different `updateOn` value. 94203 * 94204 * ```ts 94205 * const arr = new FormArray([ 94206 * new FormControl() 94207 * ], {updateOn: 'blur'}); 94208 * ``` 94209 * 94210 * ### Adding or removing controls from a form array 94211 * 94212 * To change the controls in the array, use the `push`, `insert`, `removeAt` or `clear` methods 94213 * in `FormArray` itself. These methods ensure the controls are properly tracked in the 94214 * form's hierarchy. Do not modify the array of `AbstractControl`s used to instantiate 94215 * the `FormArray` directly, as that result in strange and unexpected behavior such 94216 * as broken change detection. 94217 * 94218 * @publicApi 94219 */ 94220 94221 94222class FormArray extends AbstractControl { 94223 /** 94224 * Creates a new `FormArray` instance. 94225 * 94226 * @param controls An array of child controls. Each child control is given an index 94227 * where it is registered. 94228 * 94229 * @param validatorOrOpts A synchronous validator function, or an array of 94230 * such functions, or an `AbstractControlOptions` object that contains validation functions 94231 * and a validation trigger. 94232 * 94233 * @param asyncValidator A single async validator or array of async validator functions 94234 * 94235 */ 94236 constructor(controls, validatorOrOpts, asyncValidator) { 94237 super(pickValidators(validatorOrOpts), pickAsyncValidators(asyncValidator, validatorOrOpts)); 94238 this.controls = controls; 94239
vendor: 10,160 bytes, lines 94240-94519
94240 this._initObservables(); 94241 94242 this._setUpdateStrategy(validatorOrOpts); 94243 94244 this._setUpControls(); 94245 94246 this.updateValueAndValidity({ 94247 onlySelf: true, 94248 // If `asyncValidator` is present, it will trigger control status change from `PENDING` to 94249 // `VALID` or `INVALID`. 94250 // The status should be broadcasted via the `statusChanges` observable, so we set `emitEvent` 94251 // to `true` to allow that during the control creation process. 94252 emitEvent: !!this.asyncValidator 94253 }); 94254 } 94255 /** 94256 * Get the `AbstractControl` at the given `index` in the array. 94257 * 94258 * @param index Index in the array to retrieve the control. If `index` is negative, it will wrap 94259 * around from the back, and if index is greatly negative (less than `-length`), the result is 94260 * undefined. This behavior is the same as `Array.at(index)`. 94261 */ 94262 94263 94264 at(index) { 94265 return this.controls[this._adjustIndex(index)]; 94266 } 94267 /** 94268 * Insert a new `AbstractControl` at the end of the array. 94269 * 94270 * @param control Form control to be inserted 94271 * @param options Specifies whether this FormArray instance should emit events after a new 94272 * control is added. 94273 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 94274 * `valueChanges` observables emit events with the latest status and value when the control is 94275 * inserted. When false, no events are emitted. 94276 */ 94277 94278 94279 push(control, options = {}) { 94280 this.controls.push(control); 94281 94282 this._registerControl(control); 94283 94284 this.updateValueAndValidity({ 94285 emitEvent: options.emitEvent 94286 }); 94287 94288 this._onCollectionChange(); 94289 } 94290 /** 94291 * Insert a new `AbstractControl` at the given `index` in the array. 94292 * 94293 * @param index Index in the array to insert the control. If `index` is negative, wraps around 94294 * from the back. If `index` is greatly negative (less than `-length`), prepends to the array. 94295 * This behavior is the same as `Array.splice(index, 0, control)`. 94296 * @param control Form control to be inserted 94297 * @param options Specifies whether this FormArray instance should emit events after a new 94298 * control is inserted. 94299 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 94300 * `valueChanges` observables emit events with the latest status and value when the control is 94301 * inserted. When false, no events are emitted. 94302 */ 94303 94304 94305 insert(index, control, options = {}) { 94306 this.controls.splice(index, 0, control); 94307 94308 this._registerControl(control); 94309 94310 this.updateValueAndValidity({ 94311 emitEvent: options.emitEvent 94312 }); 94313 } 94314 /** 94315 * Remove the control at the given `index` in the array. 94316 * 94317 * @param index Index in the array to remove the control. If `index` is negative, wraps around 94318 * from the back. If `index` is greatly negative (less than `-length`), removes the first 94319 * element. This behavior is the same as `Array.splice(index, 1)`. 94320 * @param options Specifies whether this FormArray instance should emit events after a 94321 * control is removed. 94322 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 94323 * `valueChanges` observables emit events with the latest status and value when the control is 94324 * removed. When false, no events are emitted. 94325 */ 94326 94327 94328 removeAt(index, options = {}) { 94329 // Adjust the index, then clamp it at no less than 0 to prevent undesired underflows. 94330 let adjustedIndex = this._adjustIndex(index); 94331 94332 if (adjustedIndex < 0) adjustedIndex = 0; 94333 if (this.controls[adjustedIndex]) this.controls[adjustedIndex]._registerOnCollectionChange(() => {}); 94334 this.controls.splice(adjustedIndex, 1); 94335 this.updateValueAndValidity({ 94336 emitEvent: options.emitEvent 94337 }); 94338 } 94339 /** 94340 * Replace an existing control. 94341 * 94342 * @param index Index in the array to replace the control. If `index` is negative, wraps around 94343 * from the back. If `index` is greatly negative (less than `-length`), replaces the first 94344 * element. This behavior is the same as `Array.splice(index, 1, control)`. 94345 * @param control The `AbstractControl` control to replace the existing control 94346 * @param options Specifies whether this FormArray instance should emit events after an 94347 * existing control is replaced with a new one. 94348 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 94349 * `valueChanges` observables emit events with the latest status and value when the control is 94350 * replaced with a new one. When false, no events are emitted. 94351 */ 94352 94353 94354 setControl(index, control, options = {}) { 94355 // Adjust the index, then clamp it at no less than 0 to prevent undesired underflows. 94356 let adjustedIndex = this._adjustIndex(index); 94357 94358 if (adjustedIndex < 0) adjustedIndex = 0; 94359 if (this.controls[adjustedIndex]) this.controls[adjustedIndex]._registerOnCollectionChange(() => {}); 94360 this.controls.splice(adjustedIndex, 1); 94361 94362 if (control) { 94363 this.controls.splice(adjustedIndex, 0, control); 94364 94365 this._registerControl(control); 94366 } 94367 94368 this.updateValueAndValidity({ 94369 emitEvent: options.emitEvent 94370 }); 94371 94372 this._onCollectionChange(); 94373 } 94374 /** 94375 * Length of the control array. 94376 */ 94377 94378 94379 get length() { 94380 return this.controls.length; 94381 } 94382 /** 94383 * Sets the value of the `FormArray`. It accepts an array that matches 94384 * the structure of the control. 94385 * 94386 * This method performs strict checks, and throws an error if you try 94387 * to set the value of a control that doesn't exist or if you exclude the 94388 * value of a control. 94389 * 94390 * @usageNotes 94391 * ### Set the values for the controls in the form array 94392 * 94393 * ``` 94394 * const arr = new FormArray([ 94395 * new FormControl(), 94396 * new FormControl() 94397 * ]); 94398 * console.log(arr.value); // [null, null] 94399 * 94400 * arr.setValue(['Nancy', 'Drew']); 94401 * console.log(arr.value); // ['Nancy', 'Drew'] 94402 * ``` 94403 * 94404 * @param value Array of values for the controls 94405 * @param options Configure options that determine how the control propagates changes and 94406 * emits events after the value changes 94407 * 94408 * * `onlySelf`: When true, each change only affects this control, and not its parent. Default 94409 * is false. 94410 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 94411 * `valueChanges` 94412 * observables emit events with the latest status and value when the control value is updated. 94413 * When false, no events are emitted. 94414 * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity 94415 * updateValueAndValidity} method. 94416 */ 94417 94418 94419 setValue(value, options = {}) { 94420 assertAllValuesPresent(this, false, value); 94421 value.forEach((newValue, index) => { 94422 assertControlPresent(this, false, index); 94423 this.at(index).setValue(newValue, { 94424 onlySelf: true, 94425 emitEvent: options.emitEvent 94426 }); 94427 }); 94428 this.updateValueAndValidity(options); 94429 } 94430 /** 94431 * Patches the value of the `FormArray`. It accepts an array that matches the 94432 * structure of the control, and does its best to match the values to the correct 94433 * controls in the group. 94434 * 94435 * It accepts both super-sets and sub-sets of the array without throwing an error. 94436 * 94437 * @usageNotes 94438 * ### Patch the values for controls in a form array 94439 * 94440 * ``` 94441 * const arr = new FormArray([ 94442 * new FormControl(), 94443 * new FormControl() 94444 * ]); 94445 * console.log(arr.value); // [null, null] 94446 * 94447 * arr.patchValue(['Nancy']); 94448 * console.log(arr.value); // ['Nancy', null] 94449 * ``` 94450 * 94451 * @param value Array of latest values for the controls 94452 * @param options Configure options that determine how the control propagates changes and 94453 * emits events after the value changes 94454 * 94455 * * `onlySelf`: When true, each change only affects this control, and not its parent. Default 94456 * is false. 94457 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 94458 * `valueChanges` observables emit events with the latest status and value when the control 94459 * value is updated. When false, no events are emitted. The configuration options are passed to 94460 * the {@link AbstractControl#updateValueAndValidity updateValueAndValidity} method. 94461 */ 94462 94463 94464 patchValue(value, options = {}) { 94465 // Even though the `value` argument type doesn't allow `null` and `undefined` values, the 94466 // `patchValue` can be called recursively and inner data structures might have these values, 94467 // so we just ignore such cases when a field containing FormArray instance receives `null` or 94468 // `undefined` as a value. 94469 if (value == null 94470 /* both `null` and `undefined` */ 94471 ) return; 94472 value.forEach((newValue, index) => { 94473 if (this.at(index)) { 94474 this.at(index).patchValue(newValue, { 94475 onlySelf: true, 94476 emitEvent: options.emitEvent 94477 }); 94478 } 94479 }); 94480 this.updateValueAndValidity(options); 94481 } 94482 /** 94483 * Resets the `FormArray` and all descendants are marked `pristine` and `untouched`, and the 94484 * value of all descendants to null or null maps. 94485 * 94486 * You reset to a specific form state by passing in an array of states 94487 * that matches the structure of the control. The state is a standalone value 94488 * or a form state object with both a value and a disabled status. 94489 * 94490 * @usageNotes 94491 * ### Reset the values in a form array 94492 * 94493 * ```ts 94494 * const arr = new FormArray([ 94495 * new FormControl(), 94496 * new FormControl() 94497 * ]); 94498 * arr.reset(['name', 'last name']); 94499 * 94500 * console.log(arr.value); // ['name', 'last name'] 94501 * ``` 94502 * 94503 * ### Reset the values in a form array and the disabled status for the first control 94504 * 94505 * ``` 94506 * arr.reset([ 94507 * {value: 'name', disabled: true}, 94508 * 'last' 94509 * ]); 94510 * 94511 * console.log(arr.value); // ['last'] 94512 * console.log(arr.at(0).status); // 'DISABLED' 94513 * ``` 94514 * 94515 * @param value Array of values for the controls 94516 * @param options Configure options that determine how the control propagates changes and 94517 * emits events after the value changes 94518 * 94519 * * `onlySelf`: When true, each change only affects this control, and n
94519ot its parent. Default 94520 * is false. 94521 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 94522 * `valueChanges` 94523 * observables emit events with the latest status and value when the control is reset. 94524 * When false, no events are emitted. 94525 * The configuration options are passed to the {@link AbstractControl#updateValueAndValidity 94526 * updateValueAndValidity} method. 94527 */ 94528 94529 94530 reset(value = [], options = {}) { 94531 this._forEachChild((control, index) => { 94532 control.reset(value[index], { 94533 onlySelf: true, 94534 emitEvent: options.emitEvent 94535 }); 94536 }); 94537 94538 this._updatePristine(options); 94539 94540 this._updateTouched(options); 94541 94542 this.updateValueAndValidity(options); 94543 } 94544 /** 94545 * The aggregate value of the array, including any disabled controls. 94546 * 94547 * Reports all values regardless of disabled status. 94548 */ 94549 94550 94551 getRawValue() { 94552 return this.controls.map(control => control.getRawValue()); 94553 } 94554 /** 94555 * Remove all controls in the `FormArray`. 94556 * 94557 * @param options Specifies whether this FormArray instance should emit events after all 94558 * controls are removed. 94559 * * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and 94560 * `valueChanges` observables emit events with the latest status and value when all controls 94561 * in this FormArray instance are removed. When false, no events are emitted. 94562 * 94563 * @usageNotes 94564 * ### Remove all elements from a FormArray 94565 * 94566 * ```ts 94567 * const arr = new FormArray([ 94568 * new FormControl(), 94569 * new FormControl() 94570 * ]); 94571 * console.log(arr.length); // 2 94572 * 94573 * arr.clear(); 94574 * console.log(arr.length); // 0 94575 * ``` 94576 * 94577 * It's a simpler and more efficient alternative to removing all elements one by one: 94578 * 94579 * ```ts 94580 * const arr = new FormArray([ 94581 * new FormControl(), 94582 * new FormControl() 94583 * ]); 94584 * 94585 * while (arr.length) { 94586 * arr.removeAt(0); 94587 * } 94588 * ``` 94589 */ 94590 94591 94592 clear(options = {}) { 94593 if (this.controls.length < 1) return; 94594 94595 this._forEachChild(control => control._registerOnCollectionChange(() => {})); 94596 94597 this.controls.splice(0); 94598 this.updateValueAndValidity({ 94599 emitEvent: options.emitEvent 94600 }); 94601 } 94602 /** 94603 * Adjusts a negative index by summing it with the length of the array. For very negative 94604 * indices, the result may remain negative. 94605 * @internal 94606 */ 94607 94608 94609 _adjustIndex(index) { 94610 return index < 0 ? index + this.length : index; 94611 } 94612 /** @internal */ 94613 94614 94615 _syncPendingControls() { 94616 let subtreeUpdated = this.controls.reduce((updated, child) => { 94617 return child._syncPendingControls() ? true : updated; 94618 }, false); 94619 if (subtreeUpdated) this.updateValueAndValidity({ 94620 onlySelf: true 94621 }); 94622 return subtreeUpdated; 94623 } 94624 /** @internal */ 94625 94626 94627 _forEachChild(cb) { 94628 this.controls.forEach((control, index) => { 94629 cb(control, index); 94630 }); 94631 } 94632 /** @internal */ 94633 94634 94635 _updateValue() { 94636 this.value = this.controls.filter(control => control.enabled || this.disabled).map(control => control.value); 94637 } 94638 /** @internal */ 94639 94640 94641 _anyControls(condition) { 94642 return this.controls.some(control => control.enabled && condition(control)); 94643 } 94644 /** @internal */ 94645 94646 94647 _setUpControls() { 94648 this._forEachChild(control => this._registerControl(control)); 94649 } 94650 /** @internal */ 94651 94652 94653 _allControlsDisabled() { 94654 for (const control of this.controls) { 94655 if (control.enabled) return false; 94656 } 94657 94658 return this.controls.length > 0 || this.disabled; 94659 } 94660 94661 _registerControl(control) { 94662 control.setParent(this); 94663 94664 control._registerOnCollectionChange(this._onCollectionChange); 94665 } 94666 /** @internal */ 94667 94668 94669 _find(name) { 94670 return this.at(name) ?? null; 94671 } 94672 94673} 94674 94675const UntypedFormArray = FormArray; 94676 94677const isFormArray = control => control instanceof FormArray; 94678/** 94679 * @license 94680 * Copyright Google LLC All Rights Reserved. 94681 * 94682 * Use of this source code is governed by an MIT-style license that can be 94683 * found in the LICENSE file at https://angular.io/license 94684 */ 94685 94686 94687function isAbstractControlOptions(options) { 94688 return !!options && (options.asyncValidators !== undefined || options.validators !== undefined || options.updateOn !== undefined); 94689} // clang-format on 94690 94691/** 94692 * @description 94693 * Creates an `AbstractControl` from a user-specified configuration. 94694 * 94695 * The `FormBuilder` provides syntactic sugar that shortens creating instances of a 94696 * `FormControl`, `FormGroup`, or `FormArray`. It reduces the amount of boilerplate needed to 94697 * build complex forms. 94698 * 94699 * @see [Reactive Forms Guide](guide/reactive-forms) 94700 * 94701 * @publicApi 94702 */ 94703 94704 94705class FormBuilder { 94706 constructor() { 94707 this.useNonNullable = false;
vendor: 5,941 bytes, lines 94708-94871
94708 } 94709 /** 94710 * @description 94711 * Returns a FormBuilder in which automatically constructed @see FormControl} elements 94712 * have `{nonNullable: true}` and are non-nullable. 94713 * 94714 * **Constructing non-nullable controls** 94715 * 94716 * When constructing a control, it will be non-nullable, and will reset to its initial value. 94717 * 94718 * ```ts 94719 * let nnfb = new FormBuilder().nonNullable; 94720 * let name = nnfb.control('Alex'); // FormControl<string> 94721 * name.reset(); 94722 * console.log(name); // 'Alex' 94723 * ``` 94724 * 94725 * **Constructing non-nullable groups or arrays** 94726 * 94727 * When constructing a group or array, all automatically created inner controls will be 94728 * non-nullable, and will reset to their initial values. 94729 * 94730 * ```ts 94731 * let nnfb = new FormBuilder().nonNullable; 94732 * let name = nnfb.group({who: 'Alex'}); // FormGroup<{who: FormControl<string>}> 94733 * name.reset(); 94734 * console.log(name); // {who: 'Alex'} 94735 * ``` 94736 * **Constructing *nullable* fields on groups or arrays** 94737 * 94738 * It is still possible to have a nullable field. In particular, any `FormControl` which is 94739 * *already* constructed will not be altered. For example: 94740 * 94741 * ```ts 94742 * let nnfb = new FormBuilder().nonNullable; 94743 * // FormGroup<{who: FormControl<string|null>}> 94744 * let name = nnfb.group({who: new FormControl('Alex')}); 94745 * name.reset(); console.log(name); // {who: null} 94746 * ``` 94747 * 94748 * Because the inner control is constructed explicitly by the caller, the builder has 94749 * no control over how it is created, and cannot exclude the `null`. 94750 */ 94751 94752 94753 get nonNullable() { 94754 const nnfb = new FormBuilder(); 94755 nnfb.useNonNullable = true; 94756 return nnfb; 94757 } 94758 94759 group(controls, options = null) { 94760 const reducedControls = this._reduceControls(controls); 94761 94762 let newOptions = {}; 94763 94764 if (isAbstractControlOptions(options)) { 94765 // `options` are `AbstractControlOptions` 94766 newOptions = options; 94767 } else if (options !== null) { 94768 // `options` are legacy form group options 94769 newOptions.validators = options.validator; 94770 newOptions.asyncValidators = options.asyncValidator; 94771 } 94772 94773 return new FormGroup(reducedControls, newOptions); 94774 } 94775 /** 94776 * @description 94777 * Constructs a new `FormRecord` instance. Accepts a single generic argument, which is an object 94778 * containing all the keys and corresponding inner control types. 94779 * 94780 * @param controls A collection of child controls. The key for each child is the name 94781 * under which it is registered. 94782 * 94783 * @param options Configuration options object for the `FormRecord`. The object should have the 94784 * `AbstractControlOptions` type and might contain the following fields: 94785 * * `validators`: A synchronous validator function, or an array of validator functions. 94786 * * `asyncValidators`: A single async validator or array of async validator functions. 94787 * * `updateOn`: The event upon which the control should be updated (options: 'change' | 'blur' 94788 * | submit'). 94789 */ 94790 94791 94792 record(controls, options = null) { 94793 const reducedControls = this._reduceControls(controls); // Cast to `any` because the inferred types are not as specific as Element. 94794 94795 94796 return new FormRecord(reducedControls, options); 94797 } 94798 /** 94799 * @description 94800 * Constructs a new `FormControl` with the given state, validators and options. Sets 94801 * `{nonNullable: true}` in the options to get a non-nullable control. Otherwise, the 94802 * control will be nullable. Accepts a single generic argument, which is the type of the 94803 * control's value. 94804 * 94805 * @param formState Initializes the control with an initial state value, or 94806 * with an object that contains both a value and a disabled status. 94807 * 94808 * @param validatorOrOpts A synchronous validator function, or an array of 94809 * such functions, or a `FormControlOptions` object that contains 94810 * validation functions and a validation trigger. 94811 * 94812 * @param asyncValidator A single async validator or array of async validator 94813 * functions. 94814 * 94815 * @usageNotes 94816 * 94817 * ### Initialize a control as disabled 94818 * 94819 * The following example returns a control with an initial value in a disabled state. 94820 * 94821 * <code-example path="forms/ts/formBuilder/form_builder_example.ts" region="disabled-control"> 94822 * </code-example> 94823 */ 94824 94825 94826 control(formState, validatorOrOpts, asyncValidator) { 94827 let newOptions = {}; 94828 94829 if (!this.useNonNullable) { 94830 return new FormControl(formState, validatorOrOpts, asyncValidator); 94831 } 94832 94833 if (isAbstractControlOptions(validatorOrOpts)) { 94834 // If the second argument is options, then they are copied. 94835 newOptions = validatorOrOpts; 94836 } else { 94837 // If the other arguments are validators, they are copied into an options object. 94838 newOptions.validators = validatorOrOpts; 94839 newOptions.asyncValidators = asyncValidator; 94840 } 94841 94842 return new FormControl(formState, { ...newOptions, 94843 nonNullable: true 94844 }); 94845 } 94846 /** 94847 * Constructs a new `FormArray` from the given array of configurations, 94848 * validators and options. Accepts a single generic argument, which is the type of each control 94849 * inside the array. 94850 * 94851 * @param controls An array of child controls or control configs. Each child control is given an 94852 * index when it is registered. 94853 * 94854 * @param validatorOrOpts A synchronous validator function, or an array of such functions, or an 94855 * `AbstractControlOptions` object that contains 94856 * validation functions and a validation trigger. 94857 * 94858 * @param asyncValidator A single async validator or array of async validator functions. 94859 */ 94860 94861 94862 array(controls, validatorOrOpts, asyncValidator) { 94863 const createdControls = controls.map(c => this._createControl(c)); // Cast to `any` because the inferred types are not as specific as Element. 94864 94865 return new FormArray(createdControls, validatorOrOpts, asyncValidator); 94866 } 94867 /** @internal */ 94868 94869 94870 _reduceControls(controls) { 94871 const createdControls = {};
94872 Object.keys(controls).forEach(controlName => { 94873 createdControls[controlName] = this._createControl(controls[controlName]); 94874 }); 94875 return createdControls; 94876 } 94877 /** @internal */ 94878 94879 94880 _createControl(controls) { 94881 if (controls instanceof FormControl) { 94882 return controls; 94883 } else if (controls instanceof AbstractControl) { 94884 // A control; just return it 94885 return controls; 94886 } else if (Array.isArray(controls)) { 94887 // ControlConfig Tuple 94888 const value = controls[0]; 94889 const validator = controls.length > 1 ? controls[1] : null; 94890 const asyncValidator = controls.length > 2 ? controls[2] : null; 94891 return this.control(value, validator, asyncValidator); 94892 } else { 94893 // T or FormControlState<T> 94894 return this.control(controls); 94895 } 94896 } 94897 94898} 94899 94900FormBuilder.ɵfac = function FormBuilder_Factory(t) { 94901 return new (t || FormBuilder)(); 94902}; 94903 94904FormBuilder.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 94905 token: FormBuilder, 94906 factory: FormBuilder.ɵfac, 94907 providedIn: ReactiveFormsModule 94908}); 94909 94910(function () { 94911 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](FormBuilder, [{ 94912 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 94913 args: [{ 94914 providedIn: ReactiveFormsModule 94915 }] 94916 }], null, null); 94917})(); 94918/** 94919 * @description 94920 * `NonNullableFormBuilder` is similar to {@link FormBuilder}, but automatically constructed 94921 * {@link FormControl} elements have `{nonNullable: true}` and are non-nullable. 94922 * 94923 * @publicApi 94924 */ 94925 94926 94927class NonNullableFormBuilder {} 94928 94929NonNullableFormBuilder.ɵfac = function NonNullableFormBuilder_Factory(t) { 94930 return new (t || NonNullableFormBuilder)(); 94931}; 94932 94933NonNullableFormBuilder.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 94934 token: NonNullableFormBuilder, 94935 factory: function () { 94936 return (() => (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(FormBuilder).nonNullable)(); 94937 }, 94938 providedIn: ReactiveFormsModule 94939}); 94940 94941(function () { 94942 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NonNullableFormBuilder, [{ 94943 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 94944 args: [{ 94945 providedIn: ReactiveFormsModule, 94946 useFactory: () => (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(FormBuilder).nonNullable 94947 }] 94948 }], null, null); 94949})(); 94950/** 94951 * UntypedFormBuilder is the same as @see FormBuilder, but it provides untyped controls. 94952 */ 94953 94954 94955class UntypedFormBuilder extends FormBuilder { 94956 group(controlsConfig, options = null) { 94957 return super.group(controlsConfig, options); 94958 } 94959 /** 94960 * Like `FormBuilder#control`, except the resulting control is untyped. 94961 */ 94962 94963 94964 control(formState, validatorOrOpts, asyncValidator) { 94965 return super.control(formState, validatorOrOpts, asyncValidator); 94966 } 94967 /** 94968 * Like `FormBuilder#array`, except the resulting array is untyped. 94969 */ 94970 94971 94972 array(controlsConfig, validatorOrOpts, asyncValidator) { 94973 return super.array(controlsConfig, validatorOrOpts, asyncValidator); 94974 } 94975 94976} 94977 94978UntypedFormBuilder.ɵfac = /* @__PURE__ */function () { 94979 let ɵUntypedFormBuilder_BaseFactory; 94980 return function UntypedFormBuilder_Factory(t) { 94981 return (ɵUntypedFormBuilder_BaseFactory || (ɵUntypedFormBuilder_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵgetInheritedFactory"](UntypedFormBuilder)))(t || UntypedFormBuilder); 94982 }; 94983}(); 94984 94985UntypedFormBuilder.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 94986 token: UntypedFormBuilder, 94987 factory: UntypedFormBuilder.ɵfac, 94988 providedIn: ReactiveFormsModule 94989}); 94990 94991(function () { 94992 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](UntypedFormBuilder, [{ 94993 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 94994 args: [{ 94995 providedIn: ReactiveFormsModule 94996 }] 94997 }], null, null); 94998})(); 94999/** 95000 * @license 95001 * Copyright Google LLC All Rights Reserved. 95002 * 95003 * Use of this source code is governed by an MIT-style license that can be 95004 * found in the LICENSE file at https://angular.io/license 95005 */ 95006 95007/** 95008 * @publicApi 95009 */ 95010 95011 95012const VERSION = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.Version('14.2.10'); 95013/** 95014 * @license 95015 * Copyright Google LLC All Rights Reserved. 95016 * 95017 * Use of this source code is governed by an MIT-style license that can be 95018 * found in the LICENSE file at https://angular.io/license 95019 */ 95020 95021/** 95022 * @license 95023 * Copyright Google LLC All Rights Reserved. 95024 * 95025 * Use of this source code is governed by an MIT-style license that can be 95026 * found in the LICENSE file at https://angular.io/license 95027 */ 95028// This file only reexports content of the `src` folder. Keep it that way. 95029 95030/** 95031 * @license 95032 * Copyright Google LLC All Rights Reserved. 95033 * 95034 * Use of this source code is governed by an MIT-style license that can be 95035 * found in the LICENSE file at https://angular.io/license 95036 */ 95037 95038/** 95039 * Generated bundle index. Do not edit. 95040 */ 95041 95042 95043 95044/***/ }), 95045 95046/***/ 6057: 95047/*!**********************************************************************************************!*\ 95048 !*** ./node_modules/@angular/platform-browser-dynamic/fesm2020/platform-browser-dynamic.mjs ***! 95049 \**********************************************************************************************/ 95050/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 95051 95052__webpack_require__.r(__webpack_exports__); 95053/* harmony export */ __webpack_require__.d(__webpack_exports__, { 95054/* harmony export */ "JitCompilerFactory": () => (/* binding */ JitCompilerFactory),
95055/* harmony export */ "RESOURCE_CACHE_PROVIDER": () => (/* binding */ RESOURCE_CACHE_PROVIDER), 95056/* harmony export */ "VERSION": () => (/* binding */ VERSION), 95057/* harmony export */ "platformBrowserDynamic": () => (/* binding */ platformBrowserDynamic), 95058/* harmony export */ "ɵINTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS": () => (/* binding */ INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS), 95059/* harmony export */ "ɵplatformCoreDynamic": () => (/* binding */ platformCoreDynamic) 95060/* harmony export */ }); 95061/* harmony import */ var _angular_compiler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/compiler */ 8781); 95062/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 2560); 95063/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/common */ 4666); 95064/* harmony import */ var _angular_platform_browser__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/platform-browser */ 4497); 95065/** 95066 * @license Angular v14.2.10 95067 * (c) 2010-2022 Google LLC. https://angular.io/ 95068 * License: MIT 95069 */ 95070 95071 95072 95073 95074 95075/** 95076 * @license 95077 * Copyright Google LLC All Rights Reserved. 95078 * 95079 * Use of this source code is governed by an MIT-style license that can be 95080 * found in the LICENSE file at https://angular.io/license 95081 */ 95082 95083const ERROR_COLLECTOR_TOKEN = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('ErrorCollector'); 95084/** 95085 * A default provider for {@link PACKAGE_ROOT_URL} that maps to '/'. 95086 */ 95087 95088const DEFAULT_PACKAGE_URL_PROVIDER = { 95089 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.PACKAGE_ROOT_URL, 95090 useValue: '/' 95091}; 95092const COMPILER_PROVIDERS = [{ 95093 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Compiler, 95094 useFactory: () => new _angular_core__WEBPACK_IMPORTED_MODULE_1__.Compiler() 95095}]; 95096/** 95097 * @publicApi 95098 * 95099 * @deprecated 95100 * Ivy JIT mode doesn't require accessing this symbol. 95101 * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for 95102 * additional context. 95103 */ 95104 95105class JitCompilerFactory { 95106 /* @internal */ 95107 constructor(defaultOptions) { 95108 const compilerOptions = { 95109 useJit: true, 95110 defaultEncapsulation: _angular_core__WEBPACK_IMPORTED_MODULE_1__.ViewEncapsulation.Emulated, 95111 missingTranslation: _angular_core__WEBPACK_IMPORTED_MODULE_1__.MissingTranslationStrategy.Warning 95112 }; 95113 this._defaultOptions = [compilerOptions, ...defaultOptions]; 95114 } 95115 95116 createCompiler(options = []) { 95117 const opts = _mergeOptions(this._defaultOptions.concat(options)); 95118 95119 const injector = _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injector.create([COMPILER_PROVIDERS, { 95120 provide: _angular_compiler__WEBPACK_IMPORTED_MODULE_0__.CompilerConfig, 95121 useFactory: () => { 95122 return new _angular_compiler__WEBPACK_IMPORTED_MODULE_0__.CompilerConfig({ 95123 // let explicit values from the compiler options overwrite options 95124 // from the app providers 95125 useJit: opts.useJit, 95126 jitDevMode: (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.isDevMode)(), 95127 // let explicit values from the compiler options overwrite options 95128 // from the app providers 95129 defaultEncapsulation: opts.defaultEncapsulation, 95130 missingTranslation: opts.missingTranslation, 95131 preserveWhitespaces: opts.preserveWhitespaces 95132 }); 95133 }, 95134 deps: [] 95135 }, opts.providers]); 95136 return injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_1__.Compiler); 95137 } 95138 95139} 95140 95141function _mergeOptions(optionsArr) { 95142 return { 95143 useJit: _lastDefined(optionsArr.map(options => options.useJit)), 95144 defaultEncapsulation: _lastDefined(optionsArr.map(options => options.defaultEncapsulation)), 95145 providers: _mergeArrays(optionsArr.map(options => options.providers)), 95146 missingTranslation: _lastDefined(optionsArr.map(options => options.missingTranslation)), 95147 preserveWhitespaces: _lastDefined(optionsArr.map(options => options.preserveWhitespaces)) 95148 }; 95149} 95150 95151function _lastDefined(args) { 95152 for (let i = args.length - 1; i >= 0; i--) { 95153 if (args[i] !== undefined) { 95154 return args[i]; 95155 } 95156 } 95157 95158 return undefined; 95159} 95160
95161function _mergeArrays(parts) { 95162 const result = []; 95163 parts.forEach(part => part && result.push(...part)); 95164 return result; 95165} 95166/** 95167 * @license 95168 * Copyright Google LLC All Rights Reserved. 95169 * 95170 * Use of this source code is governed by an MIT-style license that can be 95171 * found in the LICENSE file at https://angular.io/license 95172 */ 95173 95174/** 95175 * A platform that included corePlatform and the compiler. 95176 * 95177 * @publicApi 95178 */ 95179 95180 95181const platformCoreDynamic = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.createPlatformFactory)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.platformCore, 'coreDynamic', [{ 95182 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.COMPILER_OPTIONS, 95183 useValue: {}, 95184 multi: true 95185}, { 95186 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.CompilerFactory, 95187 useClass: JitCompilerFactory, 95188 deps: [_angular_core__WEBPACK_IMPORTED_MODULE_1__.COMPILER_OPTIONS] 95189}]); 95190/** 95191 * @license 95192 * Copyright Google LLC All Rights Reserved. 95193 * 95194 * Use of this source code is governed by an MIT-style license that can be 95195 * found in the LICENSE file at https://angular.io/license 95196 */ 95197 95198class ResourceLoaderImpl extends _angular_compiler__WEBPACK_IMPORTED_MODULE_0__.ResourceLoader { 95199 get(url) { 95200 let resolve; 95201 let reject; 95202 const promise = new Promise((res, rej) => { 95203 resolve = res; 95204 reject = rej; 95205 }); 95206 const xhr = new XMLHttpRequest(); 95207 xhr.open('GET', url, true); 95208 xhr.responseType = 'text'; 95209 95210 xhr.onload = function () { 95211 // responseText is the old-school way of retrieving response (supported by IE8 & 9) 95212 // response/responseType properties were introduced in ResourceLoader Level2 spec (supported 95213 // by IE10) 95214 const response = xhr.response || xhr.responseText; // normalize IE9 bug (https://bugs.jquery.com/ticket/1450) 95215 95216 let status = xhr.status === 1223 ? 204 : xhr.status; // fix status code when it is 0 (0 status is undocumented). 95217 // Occurs when accessing file resources or on Android 4.1 stock browser 95218 // while retrieving files from application cache. 95219 95220 if (status === 0) { 95221 status = response ? 200 : 0; 95222 } 95223 95224 if (200 <= status && status <= 300) { 95225 resolve(response); 95226 } else { 95227 reject(`Failed to load ${url}`); 95228 } 95229 }; 95230 95231 xhr.onerror = function () { 95232 reject(`Failed to load ${url}`); 95233 }; 95234 95235 xhr.send(); 95236 return promise; 95237 } 95238 95239} 95240 95241ResourceLoaderImpl.ɵfac = /* @__PURE__ */function () { 95242 let ɵResourceLoaderImpl_BaseFactory; 95243 return function ResourceLoaderImpl_Factory(t) { 95244 return (ɵResourceLoaderImpl_BaseFactory || (ɵResourceLoaderImpl_BaseFactory = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵgetInheritedFactory"](ResourceLoaderImpl)))(t || ResourceLoaderImpl); 95245 }; 95246}(); 95247 95248ResourceLoaderImpl.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 95249 token: ResourceLoaderImpl, 95250 factory: ResourceLoaderImpl.ɵfac 95251}); 95252 95253(function () { 95254 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](ResourceLoaderImpl, [{ 95255 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable 95256 }], null, null); 95257})(); 95258/** 95259 * @license 95260 * Copyright Google LLC All Rights Reserved. 95261 * 95262 * Use of this source code is governed by an MIT-style license that can be 95263 * found in the LICENSE file at https://angular.io/license 95264 */ 95265 95266/** 95267 * @publicApi 95268 */ 95269 95270 95271const INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS = [_angular_platform_browser__WEBPACK_IMPORTED_MODULE_2__["ɵINTERNAL_BROWSER_PLATFORM_PROVIDERS"], { 95272 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.COMPILER_OPTIONS, 95273 useValue: { 95274 providers: [{ 95275 provide: _angular_compiler__WEBPACK_IMPORTED_MODULE_0__.ResourceLoader, 95276 useClass: ResourceLoaderImpl, 95277 deps: [] 95278 }] 95279 }, 95280 multi: true 95281}, { 95282 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.PLATFORM_ID, 95283 useValue: _angular_common__WEBPACK_IMPORTED_MODULE_3__["ɵPLATFORM_BROWSER_ID"] 95284}]; 95285/** 95286 * @license 95287 * Copyright Google LLC All Rights Reserved. 95288 * 95289 * Use of this source code is governed by an MIT-style license that can be 95290 * found in the LICENSE file at https://angular.io/license 95291 */ 95292 95293/** 95294 * An implementation of ResourceLoader that uses a template cache to avoid doing an actual 95295 * ResourceLoader. 95296 * 95297 * The template cache needs to be built and loaded into window.$templateCache 95298 * via a separate mechanism. 95299 * 95300 * @publicApi 95301 * 95302 * @deprecated This was previously necessary in some cases to test AOT-compiled components with View 95303 * Engine, but is no longer since Ivy. 95304 */ 95305 95306class CachedResourceLoader extends _angular_compiler__WEBPACK_IMPORTED_MODULE_0__.Re
95306sourceLoader { 95307 constructor() { 95308 super(); 95309 this._cache = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].$templateCache; 95310 95311 if (this._cache == null) { 95312 throw new Error('CachedResourceLoader: Template cache was not found in $templateCache.'); 95313 } 95314 } 95315 95316 get(url) { 95317 if (this._cache.hasOwnProperty(url)) { 95318 return Promise.resolve(this._cache[url]); 95319 } else { 95320 return Promise.reject('CachedResourceLoader: Did not find cached template for ' + url); 95321 } 95322 } 95323 95324} 95325/** 95326 * @license 95327 * Copyright Google LLC All Rights Reserved. 95328 * 95329 * Use of this source code is governed by an MIT-style license that can be 95330 * found in the LICENSE file at https://angular.io/license 95331 */ 95332 95333/** 95334 * @license 95335 * Copyright Google LLC All Rights Reserved. 95336 * 95337 * Use of this source code is governed by an MIT-style license that can be 95338 * found in the LICENSE file at https://angular.io/license 95339 */ 95340 95341/** 95342 * @publicApi 95343 */ 95344 95345 95346const VERSION = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.Version('14.2.10'); 95347/** 95348 * @license 95349 * Copyright Google LLC All Rights Reserved. 95350 * 95351 * Use of this source code is governed by an MIT-style license that can be 95352 * found in the LICENSE file at https://angular.io/license 95353 */ 95354 95355/** 95356 * @publicApi 95357 * 95358 * @deprecated This was previously necessary in some cases to test AOT-compiled components with View 95359 * Engine, but is no longer since Ivy. 95360 95361 */ 95362 95363const RESOURCE_CACHE_PROVIDER = [{ 95364 provide: _angular_compiler__WEBPACK_IMPORTED_MODULE_0__.ResourceLoader, 95365 useClass: CachedResourceLoader, 95366 deps: [] 95367}]; 95368/** 95369 * @publicApi 95370 */ 95371 95372const platformBrowserDynamic = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.createPlatformFactory)(platformCoreDynamic, 'browserDynamic', INTERNAL_BROWSER_DYNAMIC_PLATFORM_PROVIDERS); 95373/** 95374 * @license 95375 * Copyright Google LLC All Rights Reserved. 95376 * 95377 * Use of this source code is governed by an MIT-style license that can be 95378 * found in the LICENSE file at https://angular.io/license 95379 */ 95380// This file only reexports content of the `src` folder. Keep it that way. 95381 95382/** 95383 * @license 95384 * Copyright Google LLC All Rights Reserved. 95385 * 95386 * Use of this source code is governed by an MIT-style license that can be 95387 * found in the LICENSE file at https://angular.io/license 95388 */ 95389 95390/** 95391 * Generated bundle index. Do not edit. 95392 */ 95393 95394 95395 95396/***/ }), 95397 95398/***/ 7146: 95399/*!************************************************************************!*\ 95400 !*** ./node_modules/@angular/platform-browser/fesm2020/animations.mjs ***! 95401 \************************************************************************/ 95402/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 95403 95404__webpack_require__.r(__webpack_exports__); 95405/* harmony export */ __webpack_require__.d(__webpack_exports__, { 95406/* harmony export */ "ANIMATION_MODULE_TYPE": () => (/* reexport safe */ _angular_core__WEBPACK_IMPORTED_MODULE_0__.ANIMATION_MODULE_TYPE), 95407/* harmony export */ "BrowserAnimationsModule": () => (/* binding */ BrowserAnimationsModule), 95408/* harmony export */ "NoopAnimationsModule": () => (/* binding */ NoopAnimationsModule), 95409/* harmony export */ "provideAnimations": () => (/* binding */ provideAnimations), 95410/* harmony export */ "provideNoopAnimations": () => (/* binding */ provideNoopAnimations), 95411/* harmony export */ "ɵAnimationRenderer": () => (/* binding */ AnimationRenderer), 95412/* harmony export */ "ɵAnimationRendererFactory": () => (/* binding */ AnimationRendererFactory), 95413/* harmony export */ "ɵBrowserAnimationBuilder": () => (/* binding */ BrowserAnimationBuilder), 95414/* harmony export */ "ɵBrowserAnimationFactory": () => (/* binding */ BrowserAnimationFactory), 95415/* harmony export */ "ɵInjectableAnimationEngine": () => (/* binding */ InjectableAnimationEngine) 95416/* harmony export */ }); 95417/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 2560); 95418/* harmony import */ var _angular_platform_browser__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/platform-browser */ 4497); 95419/* harmony import */ var _angular_animations__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/animations */ 4851); 95420/* harmony import */ var _angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/animations/browser */ 5787); 95421/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/common */ 4666); 95422/** 95423 * @license Angular v14.2.10 95424 * (c) 2010-2022 Google LLC. https://angular.io/ 95425 * License: MIT 95426 */ 95427 95428 95429 95430 95431 95432 95433 95434 95435/** 95436 * @license 95437 * Copyright Google LLC All Rights Reserved. 95438 * 95439 * Use of this source code is governed by an MIT-style license that can be 95440 * found in the LICENSE file at https://angular.io/license 95441 */ 95442 95443class BrowserAnimationBuilder extends _angular_animations__WEBPACK_IMPORTED_MODULE_1__.AnimationBuilder { 95444 constructor(rootRenderer, doc) { 95445 super(); 95446 this._nextAnimationId = 0; 95447 const typeData = { 95448 id: '0', 95449 encapsulation: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewEncapsulation.None, 95450 styles: [], 95451 data: { 95452 animation: [] 95453 } 95454 }; 95455 this._renderer = rootRenderer.createRenderer(doc.body, typeData); 95456 } 95457 95458 build(animation) { 95459 const id = this._nextAnimationId.toString(); 95460 95461 this._nextAnimationId++; 95462 const entry = Array.isArray(animation) ? (0,_angular_animations__WEBPACK_IMPORTED_MODULE_1__.sequence)(animation) : animation; 95463 issueAnimationCommand(this._renderer, null, id, 'register', [entry]); 95464 return new BrowserAnimationFactory(id, this._renderer); 95465 } 95466 95467} 95468 95469BrowserAnimationBuilder.ɵfac = function BrowserAnimationBuilder_Factory(t) { 95470 return new (t || BrowserAnimationBuilder)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.RendererFactory2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_2__.DOCUMENT)); 95471}; 95472 95473BrowserAnimationBuilder.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 95474 token: BrowserAnimationBuilder, 95475 factory: BrowserAnimationBuilder.ɵfac 95476}); 95477 95478(function () { 95479 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](BrowserAnimationBuilder, [{ 95480 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable 95481 }], function () { 95482 return [{ 95483 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.RendererFactory2 95484 }, {
95485 type: undefined, 95486 decorators: [{ 95487 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 95488 args: [_angular_common__WEBPACK_IMPORTED_MODULE_2__.DOCUMENT] 95489 }] 95490 }]; 95491 }, null); 95492})(); 95493 95494class BrowserAnimationFactory extends _angular_animations__WEBPACK_IMPORTED_MODULE_1__.AnimationFactory { 95495 constructor(_id, _renderer) { 95496 super(); 95497 this._id = _id; 95498 this._renderer = _renderer; 95499 } 95500 95501 create(element, options) { 95502 return new RendererAnimationPlayer(this._id, element, options || {}, this._renderer); 95503 } 95504 95505} 95506 95507class RendererAnimationPlayer { 95508 constructor(id, element, options, _renderer) { 95509 this.id = id; 95510 this.element = element; 95511 this._renderer = _renderer; 95512 this.parentPlayer = null; 95513 this._started = false; 95514 this.totalTime = 0; 95515 95516 this._command('create', options); 95517 } 95518 95519 _listen(eventName, callback) { 95520 return this._renderer.listen(this.element, `@@${this.id}:${eventName}`, callback); 95521 } 95522 95523 _command(command, ...args) { 95524 return issueAnimationCommand(this._renderer, this.element, this.id, command, args); 95525 } 95526 95527 onDone(fn) { 95528 this._listen('done', fn); 95529 } 95530 95531 onStart(fn) { 95532 this._listen('start', fn); 95533 } 95534 95535 onDestroy(fn) { 95536 this._listen('destroy', fn); 95537 } 95538 95539 init() { 95540 this._command('init'); 95541 } 95542 95543 hasStarted() { 95544 return this._started; 95545 } 95546 95547 play() { 95548 this._command('play'); 95549 95550 this._started = true; 95551 } 95552 95553 pause() { 95554 this._command('pause'); 95555 } 95556 95557 restart() { 95558 this._command('restart'); 95559 } 95560 95561 finish() { 95562 this._command('finish'); 95563 } 95564 95565 destroy() { 95566 this._command('destroy'); 95567 } 95568 95569 reset() { 95570 this._command('reset'); 95571 95572 this._started = false; 95573 } 95574 95575 setPosition(p) { 95576 this._command('setPosition', p); 95577 } 95578 95579 getPosition() { 95580 return this._renderer.engine.players[+this.id]?.getPosition() ?? 0; 95581 } 95582 95583} 95584 95585function issueAnimationCommand(renderer, element, id, command, args) { 95586 return renderer.setProperty(element, `@@${id}:${command}`, args); 95587} 95588 95589const ANIMATION_PREFIX = '@'; 95590const DISABLE_ANIMATIONS_FLAG = '@.disabled'; 95591 95592class AnimationRendererFactory { 95593 constructor(delegate, engine, _zone) { 95594 this.delegate = delegate; 95595 this.engine = engine; 95596 this._zone = _zone; 95597 this._currentId = 0; 95598 this._microtaskId = 1; 95599 this._animationCallbacksBuffer = []; 95600 this._rendererCache = new Map(); 95601 this._cdRecurDepth = 0; 95602 this.promise = Promise.resolve(0); 95603 95604 engine.onRemovalComplete = (element, delegate) => { 95605 // Note: if a component element has a leave animation, and a host leave animation, 95606 // the view engine will call `removeChild` for the parent 95607 // component renderer as well as for the child component renderer. 95608 // Therefore, we need to check if we already removed the element. 95609 const parentNode = delegate?.parentNode(element); 95610 95611 if (parentNode) { 95612 delegate.removeChild(parentNode, element); 95613 } 95614 }; 95615 } 95616 95617 createRenderer(hostElement, type) { 95618 const EMPTY_NAMESPACE_ID = ''; // cache the delegates to find out which cached delegate can 95619 // be used by which cached renderer 95620 95621 const delegate = this.delegate.createRenderer(hostElement, type); 95622 95623 if (!hostElement || !type || !type.data || !type.data['animation']) { 95624 let renderer = this._rendererCache.get(delegate); 95625 95626 if (!renderer) { 95627 // Ensure that the renderer is removed from the cache on destroy 95628 // since it may contain references to detached DOM nodes. 95629 const onRendererDestroy = () => this._rendererCache.delete(delegate); 95630 95631 renderer = new BaseAnimationRenderer(EMPTY_NAMESPACE_ID, delegate, this.engine, onRendererDestroy); // only cache this result when the base renderer is used 95632 95633 this._rendererCache.set(delegate, renderer); 95634 } 95635 95636 return renderer; 95637 } 95638 95639 const componentId = type.id; 95640 const namespaceId = type.id + '-' + this._currentId; 95641 this._currentId++; 95642 this.engine.register(namespaceId, hostElement); 95643 95644 const registerTrigger = trigger => { 95645 if (Array.isArray(trigger)) { 95646 trigger.forEach(registerTrigger); 95647 } else { 95648 this.engine.registerTrigger(componentId, namespaceId, hostElement, trigger.name, trigger); 95649 } 95650 }; 95651 95652 const animationTriggers = type.data['animation'];
95653 animationTriggers.forEach(registerTrigger); 95654 return new AnimationRenderer(this, namespaceId, delegate, this.engine); 95655 } 95656 95657 begin() { 95658 this._cdRecurDepth++; 95659 95660 if (this.delegate.begin) { 95661 this.delegate.begin(); 95662 } 95663 } 95664 95665 _scheduleCountTask() { 95666 // always use promise to schedule microtask instead of use Zone 95667 this.promise.then(() => { 95668 this._microtaskId++; 95669 }); 95670 } 95671 /** @internal */ 95672 95673 95674 scheduleListenerCallback(count, fn, data) { 95675 if (count >= 0 && count < this._microtaskId) { 95676 this._zone.run(() => fn(data)); 95677 95678 return; 95679 } 95680 95681 if (this._animationCallbacksBuffer.length == 0) { 95682 Promise.resolve(null).then(() => { 95683 this._zone.run(() => { 95684 this._animationCallbacksBuffer.forEach(tuple => { 95685 const [fn, data] = tuple; 95686 fn(data); 95687 }); 95688 95689 this._animationCallbacksBuffer = []; 95690 }); 95691 }); 95692 } 95693 95694 this._animationCallbacksBuffer.push([fn, data]); 95695 } 95696 95697 end() { 95698 this._cdRecurDepth--; // this is to prevent animations from running twice when an inner 95699 // component does CD when a parent component instead has inserted it 95700 95701 if (this._cdRecurDepth == 0) { 95702 this._zone.runOutsideAngular(() => { 95703 this._scheduleCountTask(); 95704 95705 this.engine.flush(this._microtaskId); 95706 }); 95707 } 95708 95709 if (this.delegate.end) { 95710 this.delegate.end(); 95711 } 95712 } 95713 95714 whenRenderingDone() { 95715 return this.engine.whenRenderingDone(); 95716 } 95717 95718} 95719 95720AnimationRendererFactory.ɵfac = function AnimationRendererFactory_Factory(t) { 95721 return new (t || AnimationRendererFactory)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.RendererFactory2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__["ɵAnimationEngine"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone)); 95722}; 95723 95724AnimationRendererFactory.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 95725 token: AnimationRendererFactory, 95726 factory: AnimationRendererFactory.ɵfac 95727}); 95728 95729(function () { 95730 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](AnimationRendererFactory, [{ 95731 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable 95732 }], function () { 95733 return [{ 95734 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.RendererFactory2 95735 }, { 95736 type: _angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__["ɵAnimationEngine"] 95737 }, { 95738 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone 95739 }]; 95740 }, null); 95741})(); 95742 95743class BaseAnimationRenderer { 95744 constructor(namespaceId, delegate, engine, _onDestroy) { 95745 this.namespaceId = namespaceId; 95746 this.delegate = delegate; 95747 this.engine = engine; 95748 this._onDestroy = _onDestroy; 95749 this.destroyNode = this.delegate.destroyNode ? n => delegate.destroyNode(n) : null; 95750 } 95751 95752 get data() { 95753 return this.delegate.data; 95754 } 95755 95756 destroy() { 95757 this.engine.destroy(this.namespaceId, this.delegate); 95758 this.delegate.destroy(); 95759 this._onDestroy?.(); 95760 } 95761 95762 createElement(name, namespace) { 95763 return this.delegate.createElement(name, namespace); 95764 } 95765 95766 createComment(value) { 95767 return this.delegate.createComment(value); 95768 } 95769 95770 createText(value) { 95771 return this.delegate.createText(value); 95772 } 95773 95774 appendChild(parent, newChild) { 95775 this.delegate.appendChild(parent, newChild); 95776 this.engine.onInsert(this.namespaceId, newChild, parent, false); 95777 } 95778 95779 insertBefore(parent, newChild, refChild, isMove = true) { 95780 this.delegate.insertBefore(parent, newChild, refChild); // If `isMove` true than we should animate this insert. 95781 95782 this.engine.onInsert(this.namespaceId, newChild, parent, isMove); 95783 } 95784 95785 removeChild(parent, oldChild, isHostElement) { 95786 this.engine.onRemove(this.namespaceId, oldChild, this.delegate, isHostElement); 95787 } 95788 95789 selectRootElement(selectorOrNode, preserveContent) { 95790 return this.delegate.selectRootElement(selectorOrNode, preserveContent); 95791 } 95792 95793 parentNode(node) { 95794 return this.delegate.parentNode(node); 95795 } 95796 95797 nextSibling(node) { 95798 return this.delegate.nextSibling(node); 95799 } 95800 95801 setAttribute(el, name, value, namespace) { 95802 this.delegate.setAttribute(el, name, value, namespace); 95803 } 95804 95805 removeAttribute(el, name, namespace) { 95806 this.delegate.removeAttribute(el, name, namespace); 95807 } 95808 95809 addClass(el, name) { 95810 this.delegate.addClass(el, name); 95811 } 95812 95813 removeClass(el, name) { 95814 this.delegate.removeClass(el, name); 95815 } 95816 95817 setStyle(el, style, value, flags) { 95818 this.delegate.setStyle(el, style, value, flags); 95819 } 95820 95821 removeStyle(el, style, flags) { 95822 this.delegate.removeStyle(el, style, flags); 95823 } 95824 95825 setProperty(el, name, value) { 95826 if (name.charAt(0) == ANIMATION_PREFIX && name == DISABLE_ANIMATIONS_FLAG) { 95827 this.disableAnimations(el, !!value); 95828 } else { 95829 this.delegate.setProperty(el, name, value); 95830 } 95831 } 95832 95833 setValue(node, value) { 95834 this.delegate.setValue(node, value); 95835 } 95836 95837 listen(target, eventName, callback) { 95838 return this.delegate.listen(target, eventName, callback); 95839 } 95840 95841 disableAnimations(element, value) { 95842 this.engine.disableAnimations(element, value); 95843 } 95844 95845} 95846 95847class AnimationRenderer extends BaseAnimationRenderer {
95848 constructor(factory, namespaceId, delegate, engine, onDestroy) { 95849 super(namespaceId, delegate, engine, onDestroy); 95850 this.factory = factory; 95851 this.namespaceId = namespaceId; 95852 } 95853 95854 setProperty(el, name, value) { 95855 if (name.charAt(0) == ANIMATION_PREFIX) { 95856 if (name.charAt(1) == '.' && name == DISABLE_ANIMATIONS_FLAG) { 95857 value = value === undefined ? true : !!value; 95858 this.disableAnimations(el, value); 95859 } else { 95860 this.engine.process(this.namespaceId, el, name.slice(1), value); 95861 } 95862 } else { 95863 this.delegate.setProperty(el, name, value); 95864 } 95865 } 95866 95867 listen(target, eventName, callback) { 95868 if (eventName.charAt(0) == ANIMATION_PREFIX) { 95869 const element = resolveElementFromTarget(target); 95870 let name = eventName.slice(1); 95871 let phase = ''; // @listener.phase is for trigger animation callbacks 95872 // @@listener is for animation builder callbacks 95873 95874 if (name.charAt(0) != ANIMATION_PREFIX) { 95875 [name, phase] = parseTriggerCallbackName(name); 95876 } 95877 95878 return this.engine.listen(this.namespaceId, element, name, phase, event => { 95879 const countId = event['_data'] || -1; 95880 this.factory.scheduleListenerCallback(countId, callback, event); 95881 }); 95882 } 95883 95884 return this.delegate.listen(target, eventName, callback); 95885 } 95886 95887} 95888 95889function resolveElementFromTarget(target) { 95890 switch (target) { 95891 case 'body': 95892 return document.body; 95893 95894 case 'document': 95895 return document; 95896 95897 case 'window': 95898 return window; 95899 95900 default: 95901 return target; 95902 } 95903} 95904 95905function parseTriggerCallbackName(triggerName) { 95906 const dotIndex = triggerName.indexOf('.'); 95907 const trigger = triggerName.substring(0, dotIndex); 95908 const phase = triggerName.slice(dotIndex + 1); 95909 return [trigger, phase]; 95910} 95911/** 95912 * @license 95913 * Copyright Google LLC All Rights Reserved. 95914 * 95915 * Use of this source code is governed by an MIT-style license that can be 95916 * found in the LICENSE file at https://angular.io/license 95917 */ 95918 95919 95920class InjectableAnimationEngine extends _angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__["ɵAnimationEngine"] { 95921 // The `ApplicationRef` is injected here explicitly to force the dependency ordering. 95922 // Since the `ApplicationRef` should be created earlier before the `AnimationEngine`, they 95923 // both have `ngOnDestroy` hooks and `flush()` must be called after all views are destroyed. 95924 constructor(doc, driver, normalizer, appRef) { 95925 super(doc.body, driver, normalizer); 95926 } 95927 95928 ngOnDestroy() { 95929 this.flush(); 95930 } 95931 95932} 95933 95934InjectableAnimationEngine.ɵfac = function InjectableAnimationEngine_Factory(t) { 95935 return new (t || InjectableAnimationEngine)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_2__.DOCUMENT), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__.AnimationDriver), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__["ɵAnimationStyleNormalizer"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ApplicationRef)); 95936}; 95937 95938InjectableAnimationEngine.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 95939 token: InjectableAnimationEngine, 95940 factory: InjectableAnimationEngine.ɵfac 95941}); 95942 95943(function () { 95944 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](InjectableAnimationEngine, [{ 95945 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable 95946 }], function () { 95947 return [{ 95948 type: undefined, 95949 decorators: [{ 95950 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 95951 args: [_angular_common__WEBPACK_IMPORTED_MODULE_2__.DOCUMENT] 95952 }] 95953 }, { 95954 type: _angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__.AnimationDriver 95955 }, { 95956 type: _angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__["ɵAnimationStyleNormalizer"] 95957 }, { 95958 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ApplicationRef 95959 }]; 95960 }, null); 95961})(); 95962 95963function instantiateDefaultStyleNormalizer() { 95964 return new _angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__["ɵWebAnimationsStyleNormalizer"](); 95965} 95966 95967function instantiateRendererFactory(renderer, engine, zone) { 95968 return new AnimationRendererFactory(renderer, engine, zone); 95969} 95970 95971const SHARED_ANIMATION_PROVIDERS = [{ 95972 provide: _angular_animations__WEBPACK_IMPORTED_MODULE_1__.AnimationBuilder, 95973 useClass: BrowserAnimationBuilder 95974}, { 95975 provide: _angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__["ɵAnimationStyleNormalizer"], 95976 useFactory: instantiateDefaultStyleNormalizer 95977}, { 95978 provide: _angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__["ɵAnimationEngine"], 95979 useClass: InjectableAnimationEngine 95980}, { 95981 provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.RendererFactory2, 95982 useFactory: instantiateRendererFactory, 95983 deps: [_angular_platform_browser__WEBPACK_IMPORTED_MODULE_4__["ɵDomRendererFactory2"], _angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__["ɵAnimationEngine"], _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone] 95984}]; 95985/** 95986 * Separate providers from the actual module so that we can do a local modification in Google3 to 95987 * include them in the BrowserModule. 95988 */ 95989 95990const BROWSER_ANIMATIONS_PROVIDERS = [{ 95991 provide: _angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__.AnimationDriver, 95992 useFactory: () => new _angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__["ɵWebAnimationsDriver"]() 95993}, { 95994 provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ANIMATION_MODULE_TYPE, 95995 useValue: 'BrowserAnimations' 95996}, ...SHARED_ANIMATION_PROVIDERS]; 95997/** 95998 * Separate providers from the actual module so that we can do a local modification in Google3 to 95999 * include them in the BrowserTestingModule. 96000 */ 96001 96002const BROWSER_NOOP_ANIMATIONS_PROVIDERS = [{ 96003 provide: _angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__.AnimationDriver, 96004 useClass: _angular_animations_browser__WEBPACK_IMPORTED_MODULE_3__["ɵNoopAnimationDriver"] 96005}, { 96006 provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ANIMATION_MODULE_TYPE, 96007 useValue: 'NoopAnimations' 96008}, ...SHARED_ANIMATION_PROVIDERS]; 96009/** 96010 * @license 96011 * Copyright Google LLC All Rights Reserved. 96012 * 96013 * Use of this source code is governed by an MIT-style license that can be 96014 * found in the LICENSE file at https://angular.io/license 96015 */ 96016 96017/** 96018 * Exports `BrowserModule` with additional [dependency-injection providers](guide/glossary#provider) 96019 * for use with animations. See [Animations](guide/animations). 96020 * @publicApi 96021 */ 96022 96023class BrowserAnimationsModule { 96024 /** 96025 * Configures the module based on the specified object. 96026 * 96027 * @param config Object used to configure the behavior of the `BrowserAnimationsModule`. 96028 * @see `BrowserAnimationsModuleConfig` 96029 * 96030 * @usageNotes 96031 * When registering the `BrowserAnimationsModule`, you can use the `withConfig` 96032 * function as follows: 96033 * ``` 96034 * @NgModule({ 96035 * imports: [BrowserAnimationsModule.withConfig(config)] 96036 * }) 96037 * class MyNgModule {} 96038 * ``` 96039 */ 96040 static withConfig(config) { 96041 return { 96042 ngModule: BrowserAnimationsModule, 96043 providers: config.disableAnimations ? BROWSER_NOOP_ANIMATIONS_PROVIDERS : BROWSER_ANIMATIONS_PROVIDERS 96044 }; 96045 } 96046 96047} 96048 96049BrowserAnimationsModule.ɵfac = function BrowserAnimationsModule_Factory(t) { 96050 return new (t || BrowserAnimationsModule)(); 96051}; 96052 96053BrowserAnimationsModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({ 96054 type: BrowserAnimationsModule, 96055 exports: [_angular_platform_browser__WEBPACK_IMPORTED_MODULE_4__.BrowserModule] 96056}); 96057BrowserAnimationsModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({ 96058 providers: BROWSER_ANIMATIONS_PROVIDERS, 96059 imports: [_angular_platform_browser__WEBPACK_IMPORTED_MODULE_4__.BrowserModule] 96060}); 96061 96062(function () { 96063 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](BrowserAnimationsModule, [{ 96064 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule, 96065 args: [{ 96066 exports: [_angular_platform_browser__WEBPACK_IMPORTED_MODULE_4__.BrowserModule], 96067 providers: BROWSER_ANIMATIONS_PROVIDERS 96068 }] 96069 }], null, null); 96070})(); 96071/**
96072 * Returns the set of [dependency-injection providers](guide/glossary#provider) 96073 * to enable animations in an application. See [animations guide](guide/animations) 96074 * to learn more about animations in Angular. 96075 * 96076 * @usageNotes 96077 * 96078 * The function is useful when you want to enable animations in an application 96079 * bootstrapped using the `bootstrapApplication` function. In this scenario there 96080 * is no need to import the `BrowserAnimationsModule` NgModule at all, just add 96081 * providers returned by this function to the `providers` list as show below. 96082 * 96083 * ```typescript 96084 * bootstrapApplication(RootComponent, { 96085 * providers: [ 96086 * provideAnimations() 96087 * ] 96088 * }); 96089 * ``` 96090 * 96091 * @publicApi 96092 * @developerPreview 96093 */ 96094 96095 96096function provideAnimations() { 96097 // Return a copy to prevent changes to the original array in case any in-place 96098 // alterations are performed to the `provideAnimations` call results in app code. 96099 return [...BROWSER_ANIMATIONS_PROVIDERS]; 96100} 96101/** 96102 * A null player that must be imported to allow disabling of animations. 96103 * @publicApi 96104 */ 96105 96106 96107class NoopAnimationsModule {} 96108 96109NoopAnimationsModule.ɵfac = function NoopAnimationsModule_Factory(t) { 96110 return new (t || NoopAnimationsModule)(); 96111}; 96112 96113NoopAnimationsModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({ 96114 type: NoopAnimationsModule, 96115 exports: [_angular_platform_browser__WEBPACK_IMPORTED_MODULE_4__.BrowserModule] 96116}); 96117NoopAnimationsModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({ 96118 providers: BROWSER_NOOP_ANIMATIONS_PROVIDERS, 96119 imports: [_angular_platform_browser__WEBPACK_IMPORTED_MODULE_4__.BrowserModule] 96120}); 96121 96122(function () { 96123 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NoopAnimationsModule, [{ 96124 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule, 96125 args: [{ 96126 exports: [_angular_platform_browser__WEBPACK_IMPORTED_MODULE_4__.BrowserModule], 96127 providers: BROWSER_NOOP_ANIMATIONS_PROVIDERS 96128 }] 96129 }], null, null); 96130})(); 96131/** 96132 * Returns the set of [dependency-injection providers](guide/glossary#provider) 96133 * to disable animations in an application. See [animations guide](guide/animations) 96134 * to learn more about animations in Angular. 96135 * 96136 * @usageNotes 96137 * 96138 * The function is useful when you want to bootstrap an application using 96139 * the `bootstrapApplication` function, but you need to disable animations 96140 * (for example, when running tests). 96141 * 96142 * ```typescript 96143 * bootstrapApplication(RootComponent, { 96144 * providers: [ 96145 * provideNoopAnimations() 96146 * ] 96147 * }); 96148 * ``` 96149 * 96150 * @publicApi 96151 * @developerPreview 96152 */ 96153 96154 96155function provideNoopAnimations() { 96156 // Return a copy to prevent changes to the original array in case any in-place 96157 // alterations are performed to the `provideNoopAnimations` call results in app code. 96158 return [...BROWSER_NOOP_ANIMATIONS_PROVIDERS]; 96159} 96160/** 96161 * @license 96162 * Copyright Google LLC All Rights Reserved. 96163 * 96164 * Use of this source code is governed by an MIT-style license that can be 96165 * found in the LICENSE file at https://angular.io/license 96166 */ 96167 96168/** 96169 * @license 96170 * Copyright Google LLC All Rights Reserved. 96171 * 96172 * Use of this source code is governed by an MIT-style license that can be 96173 * found in the LICENSE file at https://angular.io/license 96174 */ 96175 96176/** 96177 * @license 96178 * Copyright Google LLC All Rights Reserved. 96179 * 96180 * Use of this source code is governed by an MIT-style license that can be 96181 * found in the LICENSE file at https://angular.io/license 96182 */ 96183 96184/** 96185 * @license 96186 * Copyright Google LLC All Rights Reserved. 96187 * 96188 * Use of this source code is governed by an MIT-style license that can be 96189 * found in the LICENSE file at https://angular.io/license 96190 */ 96191 96192/** 96193 * Generated bundle index. Do not edit. 96194 */ 96195 96196 96197 96198 96199/***/ }), 96200 96201/***/ 4497: 96202/*!******************************************************************************!*\ 96203 !*** ./node_modules/@angular/platform-browser/fesm2020/platform-browser.mjs ***! 96204 \******************************************************************************/ 96205/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 96206 96207__webpack_require__.r(__webpack_exports__); 96208/* harmony export */ __webpack_require__.d(__webpack_exports__, { 96209/* harmony export */ "BrowserModule": () => (/* binding */ BrowserModule), 96210/* harmony export */ "BrowserTransferStateModule": () => (/* binding */ BrowserTransferStateModule), 96211/* harmony export */ "By": () => (/* binding */ By),
96212/* harmony export */ "DomSanitizer": () => (/* binding */ DomSanitizer), 96213/* harmony export */ "EVENT_MANAGER_PLUGINS": () => (/* binding */ EVENT_MANAGER_PLUGINS), 96214/* harmony export */ "EventManager": () => (/* binding */ EventManager), 96215/* harmony export */ "HAMMER_GESTURE_CONFIG": () => (/* binding */ HAMMER_GESTURE_CONFIG), 96216/* harmony export */ "HAMMER_LOADER": () => (/* binding */ HAMMER_LOADER), 96217/* harmony export */ "HammerGestureConfig": () => (/* binding */ HammerGestureConfig), 96218/* harmony export */ "HammerModule": () => (/* binding */ HammerModule), 96219/* harmony export */ "Meta": () => (/* binding */ Meta), 96220/* harmony export */ "Title": () => (/* binding */ Title), 96221/* harmony export */ "TransferState": () => (/* binding */ TransferState), 96222/* harmony export */ "VERSION": () => (/* binding */ VERSION), 96223/* harmony export */ "bootstrapApplication": () => (/* binding */ bootstrapApplication), 96224/* harmony export */ "createApplication": () => (/* binding */ createApplication), 96225/* harmony export */ "disableDebugTools": () => (/* binding */ disableDebugTools), 96226/* harmony export */ "enableDebugTools": () => (/* binding */ enableDebugTools), 96227/* harmony export */ "makeStateKey": () => (/* binding */ makeStateKey), 96228/* harmony export */ "platformBrowser": () => (/* binding */ platformBrowser), 96229/* harmony export */ "provideProtractorTestingSupport": () => (/* binding */ provideProtractorTestingSupport), 96230/* harmony export */ "ɵBrowserDomAdapter": () => (/* binding */ BrowserDomAdapter), 96231/* harmony export */ "ɵBrowserGetTestability": () => (/* binding */ BrowserGetTestability), 96232/* harmony export */ "ɵDomEventsPlugin": () => (/* binding */ DomEventsPlugin), 96233/* harmony export */ "ɵDomRendererFactory2": () => (/* binding */ DomRendererFactory2), 96234/* harmony export */ "ɵDomSanitizerImpl": () => (/* binding */ DomSanitizerImpl), 96235/* harmony export */ "ɵDomSharedStylesHost": () => (/* binding */ DomSharedStylesHost), 96236/* harmony export */ "ɵHammerGesturesPlugin": () => (/* binding */ HammerGesturesPlugin), 96237/* harmony export */ "ɵINTERNAL_BROWSER_PLATFORM_PROVIDERS": () => (/* binding */ INTERNAL_BROWSER_PLATFORM_PROVIDERS), 96238/* harmony export */ "ɵKeyEventsPlugin": () => (/* binding */ KeyEventsPlugin), 96239/* harmony export */ "ɵNAMESPACE_URIS": () => (/* binding */ NAMESPACE_URIS), 96240/* harmony export */ "ɵSharedStylesHost": () => (/* binding */ SharedStylesHost), 96241/* harmony export */ "ɵTRANSITION_ID": () => (/* binding */ TRANSITION_ID), 96242/* harmony export */ "ɵescapeHtml": () => (/* binding */ escapeHtml), 96243/* harmony export */ "ɵflattenStyles": () => (/* binding */ flattenStyles), 96244/* harmony export */ "ɵgetDOM": () => (/* reexport safe */ _angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"]), 96245/* harmony export */ "ɵinitDomAdapter": () => (/* binding */ initDomAdapter), 96246/* harmony export */ "ɵshimContentAttribute": () => (/* binding */ shimContentAttribute), 96247/* harmony export */ "ɵshimHostAttribute": () => (/* binding */ shimHostAttribute) 96248/* harmony export */ }); 96249/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/common */ 4666); 96250/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 2560); 96251/** 96252 * @license Angular v14.2.10 96253 * (c) 2010-2022 Google LLC. https://angular.io/ 96254 * License: MIT 96255 */ 96256 96257 96258 96259 96260/** 96261 * @license 96262 * Copyright Google LLC All Rights Reserved. 96263 * 96264 * Use of this source code is governed by an MIT-style license that can be 96265 * found in the LICENSE file at https://angular.io/license 96266 */ 96267 96268/** 96269 * Provides DOM operations in any browser environment. 96270 * 96271 * @security Tread carefully! Interacting with the DOM directly is dangerous and 96272 * can introduce XSS risks. 96273 */ 96274 96275class GenericBrowserDomAdapter extends _angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵDomAdapter"] { 96276 constructor() { 96277 super(...arguments); 96278 this.supportsDOMEvents = true; 96279 } 96280 96281} 96282/** 96283 * @license 96284 * Copyright Google LLC All Rights Reserved. 96285 * 96286 * Use of this source code is governed by an MIT-style license that can be 96287 * found in the LICENSE file at https://angular.io/license 96288 */ 96289 96290/** 96291 * A `DomAdapter` powered by full browser DOM APIs. 96292 * 96293 * @security Tread carefully! Interacting with the DOM directly is dangerous and 96294 * can introduce XSS risks. 96295 */ 96296 96297/* tslint:disable:requireParameterType no-console */ 96298 96299 96300class BrowserDomAdapter extends GenericBrowserDomAdapter { 96301 static makeCurrent() { 96302 (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵsetRootDomAdapter"])(new BrowserDomAdapter()); 96303 } 96304 96305 onAndCancel(el, evt, listener) { 96306 el.addEventListener(evt, listener, false); // Needed to follow Dart's subscription semantic, until fix of 96307 // https://code.google.com/p/dart/issues/detail?id=17406 96308 96309 return () => { 96310 el.removeEventListener(evt, listener, false); 96311 }; 96312 } 96313 96314 dispatchEvent(el, evt) { 96315 el.dispatchEvent(evt); 96316 } 96317 96318 remove(node) { 96319 if (node.parentNode) { 96320 node.parentNode.removeChild(node); 96321 } 96322 } 96323 96324 createElement(tagName, doc) { 96325 doc = doc || this.getDefaultDocument(); 96326 return doc.createElement(tagName); 96327 } 96328 96329 createHtmlDocument() { 96330 return document.implementation.createHTMLDocument('fakeTitle'); 96331 } 96332 96333 getDefaultDocument() { 96334 return document; 96335 } 96336 96337 isElementNode(node) { 96338 return node.nodeType === Node.ELEMENT_NODE; 96339 } 96340 96341 isShadowRoot(node) { 96342 return node instanceof DocumentFragment; 96343 } 96344 /** @deprecated No longer being used in Ivy code. To be removed in version 14. */ 96345 96346 96347 getGlobalEventTarget(doc, target) { 96348 if (target === 'window') { 96349 return window; 96350 } 96351 96352 if (target === 'document') { 96353 return doc; 96354 } 96355 96356 if (target === 'body') { 96357 return doc.body; 96358 } 96359 96360 return null; 96361 } 96362 96363 getBaseHref(doc) { 96364 const href = getBaseElementHref(); 96365 return href == null ? null : relativePath(href); 96366 } 96367 96368 resetBaseElement() { 96369 baseElement = null; 96370 } 96371 96372 getUserAgent() { 96373 return window.navigator.userAgent; 96374 } 96375 96376 getCookie(name) { 96377 return (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵparseCookieValue"])(document.cookie, name); 96378 } 96379 96380} 96381 96382let baseElement = null; 96383 96384function getBaseElementHref() { 96385 baseElement = baseElement || document.querySelector('base'); 96386 return baseElement ? baseElement.getAttribute('href') : null; 96387} // based on urlUtils.js in AngularJS 1 96388 96389 96390let urlParsingNode; 96391 96392function relativePath(url) { 96393 urlParsingNode = urlParsingNode || document.createElement('a'); 96394 urlParsingNode.setAttribute('href', url); 96395 const pathName = urlParsingNode.pathname; 96396 return pathName.charAt(0) === '/' ? pathName : `/${pathName}`; 96397} 96398/** 96399 * @license 96400 * Copyright Google LLC All Rights Reserved. 96401 * 96402 * Use of this source code is governed by an MIT-style license that can be 96403 * found in the LICENSE file at https://angular.io/license 96404 */ 96405 96406/** 96407 * An id that identifies a particular application being bootstrapped, that should 96408 * match across the client/server boundary. 96409 */ 96410 96411 96412const TRANSITION_ID = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('TRANSITION_ID'); 96413 96414function appInitializerFactory(transitionId, document, injector) { 96415 return () => {
96416 // Wait for all application initializers to be completed before removing the styles set by 96417 // the server. 96418 injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_1__.ApplicationInitStatus).donePromise.then(() => { 96419 const dom = (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"])(); 96420 const styles = document.querySelectorAll(`style[ng-transition="${transitionId}"]`); 96421 96422 for (let i = 0; i < styles.length; i++) { 96423 dom.remove(styles[i]); 96424 } 96425 }); 96426 }; 96427} 96428 96429const SERVER_TRANSITION_PROVIDERS = [{ 96430 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_INITIALIZER, 96431 useFactory: appInitializerFactory, 96432 deps: [TRANSITION_ID, _angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT, _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injector], 96433 multi: true 96434}]; 96435/** 96436 * @license 96437 * Copyright Google LLC All Rights Reserved. 96438 * 96439 * Use of this source code is governed by an MIT-style license that can be 96440 * found in the LICENSE file at https://angular.io/license 96441 */ 96442 96443class BrowserGetTestability { 96444 addToWindow(registry) { 96445 _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].getAngularTestability = (elem, findInAncestors = true) => { 96446 const testability = registry.findTestabilityInTree(elem, findInAncestors); 96447 96448 if (testability == null) { 96449 throw new Error('Could not find testability for element.'); 96450 } 96451 96452 return testability; 96453 }; 96454 96455 _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].getAllAngularTestabilities = () => registry.getAllTestabilities(); 96456 96457 _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].getAllAngularRootElements = () => registry.getAllRootElements(); 96458 96459 const whenAllStable = (callback 96460 /** TODO #9100 */ 96461 ) => { 96462 const testabilities = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].getAllAngularTestabilities(); 96463 let count = testabilities.length; 96464 let didWork = false; 96465 96466 const decrement = function (didWork_ 96467 /** TODO #9100 */ 96468 ) { 96469 didWork = didWork || didWork_; 96470 count--; 96471 96472 if (count == 0) { 96473 callback(didWork); 96474 } 96475 }; 96476 96477 testabilities.forEach(function (testability 96478 /** TODO #9100 */ 96479 ) { 96480 testability.whenStable(decrement); 96481 }); 96482 }; 96483 96484 if (!_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].frameworkStabilizers) { 96485 _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].frameworkStabilizers = []; 96486 } 96487 96488 _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].frameworkStabilizers.push(whenAllStable); 96489 } 96490 96491 findTestabilityInTree(registry, elem, findInAncestors) { 96492 if (elem == null) { 96493 return null; 96494 } 96495 96496 const t = registry.getTestability(elem); 96497 96498 if (t != null) { 96499 return t; 96500 } else if (!findInAncestors) { 96501 return null; 96502 } 96503 96504 if ((0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"])().isShadowRoot(elem)) { 96505 return this.findTestabilityInTree(registry, elem.host, true); 96506 } 96507 96508 return this.findTestabilityInTree(registry, elem.parentElement, true); 96509 } 96510 96511} 96512/** 96513 * A factory for `HttpXhrBackend` that uses the `XMLHttpRequest` browser API. 96514 */ 96515 96516 96517class BrowserXhr { 96518 build() { 96519 return new XMLHttpRequest(); 96520 } 96521 96522} 96523 96524BrowserXhr.ɵfac = function BrowserXhr_Factory(t) { 96525 return new (t || BrowserXhr)(); 96526}; 96527 96528BrowserXhr.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 96529 token: BrowserXhr, 96530 factory: BrowserXhr.ɵfac 96531}); 96532 96533(function () { 96534 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](BrowserXhr, [{ 96535 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable 96536 }], null, null); 96537})(); 96538/** 96539 * @license 96540 * Copyright Google LLC All Rights Reserved. 96541 * 96542 * Use of this source code is governed by an MIT-style license that can be 96543 * found in the LICENSE file at https://angular.io/license 96544 */ 96545 96546/** 96547 * The injection token for the event-manager plug-in service. 96548 * 96549 * @publicApi 96550 */ 96551 96552 96553const EVENT_MANAGER_PLUGINS = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('EventManagerPlugins'); 96554/** 96555 * An injectable service that provides event management for Angular 96556 * through a browser plug-in. 96557 * 96558 * @publicApi 96559 */ 96560 96561class EventManager { 96562 /** 96563 * Initializes an instance of the event-manager service. 96564 */ 96565 constructor(plugins, _zone) { 96566 this._zone = _zone; 96567 this._eventNameToPlugin = new Map(); 96568 plugins.forEach(p => p.manager = this); 96569 this._plugins = plugins.slice().reverse(); 96570 } 96571 /** 96572 * Registers a handler for a specific element and event. 96573 * 96574 * @param element The HTML element to receive event notifications. 96575 * @param eventName The name of the event to listen for. 96576 * @param handler A function to call when the notification occurs. Receives the 96577 * event object as an argument.
96578 * @returns A callback function that can be used to remove the handler. 96579 */ 96580 96581 96582 addEventListener(element, eventName, handler) { 96583 const plugin = this._findPluginFor(eventName); 96584 96585 return plugin.addEventListener(element, eventName, handler); 96586 } 96587 /** 96588 * Registers a global handler for an event in a target view. 96589 * 96590 * @param target A target for global event notifications. One of "window", "document", or "body". 96591 * @param eventName The name of the event to listen for. 96592 * @param handler A function to call when the notification occurs. Receives the 96593 * event object as an argument. 96594 * @returns A callback function that can be used to remove the handler. 96595 * @deprecated No longer being used in Ivy code. To be removed in version 14. 96596 */ 96597 96598 96599 addGlobalEventListener(target, eventName, handler) { 96600 const plugin = this._findPluginFor(eventName); 96601 96602 return plugin.addGlobalEventListener(target, eventName, handler); 96603 } 96604 /** 96605 * Retrieves the compilation zone in which event listeners are registered. 96606 */ 96607 96608 96609 getZone() { 96610 return this._zone; 96611 } 96612 /** @internal */ 96613 96614 96615 _findPluginFor(eventName) { 96616 const plugin = this._eventNameToPlugin.get(eventName); 96617 96618 if (plugin) { 96619 return plugin; 96620 } 96621 96622 const plugins = this._plugins; 96623 96624 for (let i = 0; i < plugins.length; i++) { 96625 const plugin = plugins[i]; 96626 96627 if (plugin.supports(eventName)) { 96628 this._eventNameToPlugin.set(eventName, plugin); 96629 96630 return plugin; 96631 } 96632 } 96633 96634 throw new Error(`No event manager plugin found for event ${eventName}`); 96635 } 96636 96637} 96638 96639EventManager.ɵfac = function EventManager_Factory(t) { 96640 return new (t || EventManager)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](EVENT_MANAGER_PLUGINS), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone)); 96641}; 96642 96643EventManager.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 96644 token: EventManager, 96645 factory: EventManager.ɵfac 96646}); 96647 96648(function () { 96649 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](EventManager, [{ 96650 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable 96651 }], function () { 96652 return [{ 96653 type: undefined, 96654 decorators: [{ 96655 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 96656 args: [EVENT_MANAGER_PLUGINS] 96657 }] 96658 }, { 96659 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone 96660 }]; 96661 }, null); 96662})(); 96663 96664class EventManagerPlugin { 96665 constructor(_doc) { 96666 this._doc = _doc; 96667 } 96668 96669 addGlobalEventListener(element, eventName, handler) { 96670 const target = (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"])().getGlobalEventTarget(this._doc, element); 96671 96672 if (!target) { 96673 throw new Error(`Unsupported event target ${target} for event ${eventName}`); 96674 } 96675 96676 return this.addEventListener(target, eventName, handler); 96677 } 96678 96679} 96680/** 96681 * @license 96682 * Copyright Google LLC All Rights Reserved. 96683 * 96684 * Use of this source code is governed by an MIT-style license that can be 96685 * found in the LICENSE file at https://angular.io/license 96686 */ 96687 96688 96689class SharedStylesHost { 96690 constructor() { 96691 /** @internal */ 96692 this._stylesSet = new Set(); 96693 } 96694 96695 addStyles(styles) { 96696 const additions = new Set(); 96697 styles.forEach(style => { 96698 if (!this._stylesSet.has(style)) { 96699 this._stylesSet.add(style); 96700 96701 additions.add(style); 96702 } 96703 }); 96704 this.onStylesAdded(additions); 96705 } 96706 96707 onStylesAdded(additions) {} 96708 96709 getAllStyles() { 96710 return Array.from(this._stylesSet); 96711 } 96712 96713} 96714 96715SharedStylesHost.ɵfac = function SharedStylesHost_Factory(t) { 96716 return new (t || SharedStylesHost)(); 96717}; 96718 96719SharedStylesHost.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 96720 token: SharedStylesHost, 96721 factory: SharedStylesHost.ɵfac 96722}); 96723 96724(function () { 96725 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](SharedStylesHost, [{ 96726 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable 96727 }], null, null); 96728})(); 96729 96730class DomSharedStylesHost extends SharedStylesHost { 96731 constructor(_doc) { 96732 super(); 96733 this._doc = _doc; // Maps all registered host nodes to a list of style nodes that have been added to the host node. 96734 96735 this._hostNodes = new Map(); 96736 96737 this._hostNodes.set(_doc.head, []); 96738 } 96739 96740 _addStylesToHost(styles, host, styleNodes) {
96741 styles.forEach(style => { 96742 const styleEl = this._doc.createElement('style'); 96743 96744 styleEl.textContent = style; 96745 styleNodes.push(host.appendChild(styleEl)); 96746 }); 96747 } 96748 96749 addHost(hostNode) { 96750 const styleNodes = []; 96751 96752 this._addStylesToHost(this._stylesSet, hostNode, styleNodes); 96753 96754 this._hostNodes.set(hostNode, styleNodes); 96755 } 96756 96757 removeHost(hostNode) { 96758 const styleNodes = this._hostNodes.get(hostNode); 96759 96760 if (styleNodes) { 96761 styleNodes.forEach(removeStyle); 96762 } 96763 96764 this._hostNodes.delete(hostNode); 96765 } 96766 96767 onStylesAdded(additions) { 96768 this._hostNodes.forEach((styleNodes, hostNode) => { 96769 this._addStylesToHost(additions, hostNode, styleNodes); 96770 }); 96771 } 96772 96773 ngOnDestroy() { 96774 this._hostNodes.forEach(styleNodes => styleNodes.forEach(removeStyle)); 96775 } 96776 96777} 96778 96779DomSharedStylesHost.ɵfac = function DomSharedStylesHost_Factory(t) { 96780 return new (t || DomSharedStylesHost)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT)); 96781}; 96782 96783DomSharedStylesHost.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 96784 token: DomSharedStylesHost, 96785 factory: DomSharedStylesHost.ɵfac 96786}); 96787 96788(function () { 96789 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](DomSharedStylesHost, [{ 96790 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable 96791 }], function () { 96792 return [{ 96793 type: undefined, 96794 decorators: [{ 96795 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 96796 args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT] 96797 }] 96798 }]; 96799 }, null); 96800})(); 96801 96802function removeStyle(styleNode) { 96803 (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"])().remove(styleNode); 96804} 96805/** 96806 * @license 96807 * Copyright Google LLC All Rights Reserved. 96808 * 96809 * Use of this source code is governed by an MIT-style license that can be 96810 * found in the LICENSE file at https://angular.io/license 96811 */ 96812 96813 96814const NAMESPACE_URIS = { 96815 'svg': 'http://www.w3.org/2000/svg', 96816 'xhtml': 'http://www.w3.org/1999/xhtml', 96817 'xlink': 'http://www.w3.org/1999/xlink', 96818 'xml': 'http://www.w3.org/XML/1998/namespace', 96819 'xmlns': 'http://www.w3.org/2000/xmlns/', 96820 'math': 'http://www.w3.org/1998/MathML/' 96821}; 96822const COMPONENT_REGEX = /%COMP%/g; 96823const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
96824const COMPONENT_VARIABLE = '%COMP%'; 96825const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`; 96826const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`; 96827 96828function shimContentAttribute(componentShortId) { 96829 return CONTENT_ATTR.replace(COMPONENT_REGEX, componentShortId); 96830} 96831 96832function shimHostAttribute(componentShortId) { 96833 return HOST_ATTR.replace(COMPONENT_REGEX, componentShortId); 96834} 96835 96836function flattenStyles(compId, styles, target) { 96837 for (let i = 0; i < styles.length; i++) { 96838 let style = styles[i]; 96839 96840 if (Array.isArray(style)) { 96841 flattenStyles(compId, style, target); 96842 } else { 96843 style = style.replace(COMPONENT_REGEX, compId); 96844 target.push(style); 96845 } 96846 } 96847 96848 return target; 96849} 96850 96851function decoratePreventDefault(eventHandler) { 96852 // `DebugNode.triggerEventHandler` needs to know if the listener was created with 96853 // decoratePreventDefault or is a listener added outside the Angular context so it can handle the 96854 // two differently. In the first case, the special '__ngUnwrap__' token is passed to the unwrap 96855 // the listener (see below). 96856 return event => { 96857 // Ivy uses '__ngUnwrap__' as a special token that allows us to unwrap the function 96858 // so that it can be invoked programmatically by `DebugNode.triggerEventHandler`. The debug_node 96859 // can inspect the listener toString contents for the existence of this special token. Because 96860 // the token is a string literal, it is ensured to not be modified by compiled code. 96861 if (event === '__ngUnwrap__') { 96862 return eventHandler; 96863 } 96864 96865 const allowDefaultBehavior = eventHandler(event); 96866 96867 if (allowDefaultBehavior === false) { 96868 // TODO(tbosch): move preventDefault into event plugins... 96869 event.preventDefault(); 96870 event.returnValue = false; 96871 } 96872 96873 return undefined; 96874 }; 96875} 96876 96877let hasLoggedNativeEncapsulationWarning = false; 96878 96879class DomRendererFactory2 { 96880 constructor(eventManager, sharedStylesHost, appId) { 96881 this.eventManager = eventManager; 96882 this.sharedStylesHost = sharedStylesHost; 96883 this.appId = appId; 96884 this.rendererByCompId = new Map(); 96885 this.defaultRenderer = new DefaultDomRenderer2(eventManager); 96886 } 96887 96888 createRenderer(element, type) { 96889 if (!element || !type) { 96890 return this.defaultRenderer; 96891 } 96892 96893 switch (type.encapsulation) { 96894 case _angular_core__WEBPACK_IMPORTED_MODULE_1__.ViewEncapsulation.Emulated: 96895 { 96896 let renderer = this.rendererByCompId.get(type.id); 96897 96898 if (!renderer) { 96899 renderer = new EmulatedEncapsulationDomRenderer2(this.eventManager, this.sharedStylesHost, type, this.appId); 96900 this.rendererByCompId.set(type.id, renderer); 96901 } 96902 96903 renderer.applyToHost(element); 96904 return renderer; 96905 } 96906 // @ts-ignore TODO: Remove as part of FW-2290. TS complains about us dealing with an enum 96907 // value that is not known (but previously was the value for ViewEncapsulation.Native) 96908 96909 case 1: 96910 case _angular_core__WEBPACK_IMPORTED_MODULE_1__.ViewEncapsulation.ShadowDom: 96911 // TODO(FW-2290): remove the `case 1:` fallback logic and the warning in v12. 96912 if ((typeof ngDevMode === 'undefined' || ngDevMode) && // @ts-ignore TODO: Remove as part of FW-2290. TS complains about us dealing with an 96913 // enum value that is not known (but previously was the value for 96914 // ViewEncapsulation.Native) 96915 !hasLoggedNativeEncapsulationWarning && type.encapsulation === 1) { 96916 hasLoggedNativeEncapsulationWarning = true; 96917 console.warn('ViewEncapsulation.Native is no longer supported. Falling back to ViewEncapsulation.ShadowDom. The fallback will be removed in v12.'); 96918 } 96919 96920 return new ShadowDomRenderer(this.eventManager, this.sharedStylesHost, element, type); 96921 96922 default: 96923 { 96924 if (!this.rendererByCompId.has(type.id)) { 96925 const styles = flattenStyles(type.id, type.styles, []); 96926 this.sharedStylesHost.addStyles(styles); 96927 this.rendererByCompId.set(type.id, this.defaultRenderer); 96928 } 96929 96930 return this.defaultRenderer; 96931 } 96932 } 96933 } 96934 96935 begin() {} 96936 96937 end() {} 96938 96939}
96939 96940 96941DomRendererFactory2.ɵfac = function DomRendererFactory2_Factory(t) { 96942 return new (t || DomRendererFactory2)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](EventManager), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](DomSharedStylesHost), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_ID)); 96943}; 96944 96945DomRendererFactory2.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 96946 token: DomRendererFactory2, 96947 factory: DomRendererFactory2.ɵfac 96948}); 96949 96950(function () { 96951 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](DomRendererFactory2, [{ 96952 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable 96953 }], function () { 96954 return [{ 96955 type: EventManager 96956 }, { 96957 type: DomSharedStylesHost 96958 }, { 96959 type: undefined, 96960 decorators: [{ 96961 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 96962 args: [_angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_ID] 96963 }] 96964 }]; 96965 }, null); 96966})(); 96967 96968class DefaultDomRenderer2 { 96969 constructor(eventManager) { 96970 this.eventManager = eventManager; 96971 this.data = Object.create(null); 96972 this.destroyNode = null; 96973 } 96974 96975 destroy() {} 96976 96977 createElement(name, namespace) { 96978 if (namespace) { 96979 // TODO: `|| namespace` was added in 96980 // https://github.com/angular/angular/commit/2b9cc8503d48173492c29f5a271b61126104fbdb to 96981 // support how Ivy passed around the namespace URI rather than short name at the time. It did 96982 // not, however extend the support to other parts of the system (setAttribute, setAttribute, 96983 // and the ServerRenderer). We should decide what exactly the semantics for dealing with 96984 // namespaces should be and make it consistent. 96985 // Related issues: 96986 // https://github.com/angular/angular/issues/44028 96987 // https://github.com/angular/angular/issues/44883 96988 return document.createElementNS(NAMESPACE_URIS[namespace] || namespace, name); 96989 } 96990 96991 return document.createElement(name); 96992 } 96993 96994 createComment(value) { 96995 return document.createComment(value); 96996 } 96997 96998 createText(value) { 96999 return document.createTextNode(value); 97000 } 97001 97002 appendChild(parent, newChild) { 97003 const targetParent = isTemplateNode(parent) ? parent.content : parent; 97004 targetParent.appendChild(newChild); 97005 } 97006 97007 insertBefore(parent, newChild, refChild) { 97008 if (parent) { 97009 const targetParent = isTemplateNode(parent) ? parent.content : parent; 97010 targetParent.insertBefore(newChild, refChild); 97011 } 97012 } 97013 97014 removeChild(parent, oldChild) { 97015 if (parent) { 97016 parent.removeChild(oldChild); 97017 } 97018 } 97019 97020 selectRootElement(selectorOrNode, preserveContent) { 97021 let el = typeof selectorOrNode === 'string' ? document.querySelector(selectorOrNode) : selectorOrNode; 97022 97023 if (!el) { 97024 throw new Error(`The selector "${selectorOrNode}" did not match any elements`); 97025 } 97026 97027 if (!preserveContent) { 97028 el.textContent = ''; 97029 } 97030 97031 return el; 97032 } 97033 97034 parentNode(node) { 97035 return node.parentNode; 97036 } 97037 97038 nextSibling(node) { 97039 return node.nextSibling; 97040 } 97041 97042 setAttribute(el, name, value, namespace) { 97043 if (namespace) { 97044 name = namespace + ':' + name; 97045 const namespaceUri = NAMESPACE_URIS[namespace]; 97046 97047 if (namespaceUri) { 97048 el.setAttributeNS(namespaceUri, name, value); 97049 } else { 97050 el.setAttribute(name, value); 97051 } 97052 } else { 97053 el.setAttribute(name, value); 97054 } 97055 } 97056 97057 removeAttribute(el, name, namespace) { 97058 if (namespace) { 97059 const namespaceUri = NAMESPACE_URIS[namespace]; 97060 97061 if (namespaceUri) { 97062 el.removeAttributeNS(namespaceUri, name); 97063 } else { 97064 el.removeAttribute(`${namespace}:${name}`); 97065 } 97066 } else { 97067 el.removeAttribute(name); 97068 } 97069 } 97070 97071 addClass(el, name) { 97072 el.classList.add(name); 97073 } 97074 97075 removeClass(el, name) { 97076 el.classList.remove(name); 97077 } 97078 97079 setStyle(el, style, value, flags) { 97080 if (flags & (_angular_core__WEBPACK_IMPORTED_MODULE_1__.RendererStyleFlags2.DashCase | _angular_core__WEBPACK_IMPORTED_MODULE_1__.RendererStyleFlags2.Important)) { 97081 el.style.setProperty(style, value, flags & _angular_core__WEBPACK_IMPORTED_MODULE_1__.RendererStyleFlags2.Important ? 'important' : ''); 97082 } else { 97083 el.style[style] = value; 97084 } 97085 } 97086 97087 removeStyle(el, style, flags) { 97088 if (flags & _angular_core__WEBPACK_IMPORTED_MODULE_1__.RendererStyleFlags2.DashCase) { 97089 el.style.removeProperty(style); 97090 } else { 97091 // IE requires '' instead of null 97092 // see https://github.com/angular/angular/issues/7916 97093 el.style[style] = ''; 97094 } 97095 } 97096 97097 setProperty(el, name, value) { 97098 NG_DEV_MODE$1 && checkNoSyntheticProp(name, 'property'); 97099 el[name] = value; 97100 } 97101 97102 setValue(node, value) { 97103 node.nodeValue = value; 97104 } 97105 97106 listen(target, event, callback) { 97107 NG_DEV_MODE$1 && checkNoSyntheticProp(event, 'listener'); 97108 97109 if (typeof target === 'string') { 97110 return this.eventManager.addGlobalEventListener(target, event, decoratePreventDefault(callback)); 97111 } 97112 97113 return this.eventManager.addEventListener(target, event, decoratePreventDefault(callback)); 97114 } 97115 97116} 97117 97118const AT_CHARCODE = (() => '@'.charCodeAt(0))(); 97119 97120function checkNoSyntheticProp(name, nameKind) { 97121 if (name.charCodeAt(0) === AT_CHARCODE) { 97122 throw new Error(`Unexpected synthetic ${nameKind} ${name} found. Please make sure that: 97123 - Either \`BrowserAnimationsModule\` or \`NoopAnimationsModule\` are imported in your application. 97124 - There is corresponding configuration for the animation named \`${name}\` defined in the \`animations\` field of the \`@Component\` decorator (see https://angular.io/api/core/Component#animations).`); 97125 } 97126} 97127 97128function isTemplateNode(node) { 97129 return node.tagName === 'TEMPLATE' && node.content !== undefined; 97130} 97131 97132class EmulatedEncapsulationDomRenderer2 extends DefaultDomRenderer2 {
97133 constructor(eventManager, sharedStylesHost, component, appId) { 97134 super(eventManager); 97135 this.component = component; 97136 const styles = flattenStyles(appId + '-' + component.id, component.styles, []); 97137 sharedStylesHost.addStyles(styles); 97138 this.contentAttr = shimContentAttribute(appId + '-' + component.id); 97139 this.hostAttr = shimHostAttribute(appId + '-' + component.id); 97140 } 97141 97142 applyToHost(element) { 97143 super.setAttribute(element, this.hostAttr, ''); 97144 } 97145 97146 createElement(parent, name) { 97147 const el = super.createElement(parent, name); 97148 super.setAttribute(el, this.contentAttr, ''); 97149 return el; 97150 } 97151 97152} 97153 97154class ShadowDomRenderer extends DefaultDomRenderer2 { 97155 constructor(eventManager, sharedStylesHost, hostEl, component) { 97156 super(eventManager); 97157 this.sharedStylesHost = sharedStylesHost; 97158 this.hostEl = hostEl; 97159 this.shadowRoot = hostEl.attachShadow({ 97160 mode: 'open' 97161 }); 97162 this.sharedStylesHost.addHost(this.shadowRoot); 97163 const styles = flattenStyles(component.id, component.styles, []); 97164 97165 for (let i = 0; i < styles.length; i++) { 97166 const styleEl = document.createElement('style'); 97167 styleEl.textContent = styles[i]; 97168 this.shadowRoot.appendChild(styleEl); 97169 } 97170 } 97171 97172 nodeOrShadowRoot(node) { 97173 return node === this.hostEl ? this.shadowRoot : node; 97174 } 97175 97176 destroy() { 97177 this.sharedStylesHost.removeHost(this.shadowRoot); 97178 } 97179 97180 appendChild(parent, newChild) { 97181 return super.appendChild(this.nodeOrShadowRoot(parent), newChild); 97182 } 97183 97184 insertBefore(parent, newChild, refChild) { 97185 return super.insertBefore(this.nodeOrShadowRoot(parent), newChild, refChild); 97186 } 97187 97188 removeChild(parent, oldChild) { 97189 return super.removeChild(this.nodeOrShadowRoot(parent), oldChild); 97190 } 97191 97192 parentNode(node) { 97193 return this.nodeOrShadowRoot(super.parentNode(this.nodeOrShadowRoot(node))); 97194 } 97195 97196} 97197/** 97198 * @license 97199 * Copyright Google LLC All Rights Reserved. 97200 * 97201 * Use of this source code is governed by an MIT-style license that can be 97202 * found in the LICENSE file at https://angular.io/license 97203 */ 97204 97205
97206class DomEventsPlugin extends EventManagerPlugin { 97207 constructor(doc) { 97208 super(doc); 97209 } // This plugin should come last in the list of plugins, because it accepts all 97210 // events. 97211 97212 97213 supports(eventName) { 97214 return true; 97215 } 97216 97217 addEventListener(element, eventName, handler) { 97218 element.addEventListener(eventName, handler, false); 97219 return () => this.removeEventListener(element, eventName, handler); 97220 } 97221 97222 removeEventListener(target, eventName, callback) { 97223 return target.removeEventListener(eventName, callback); 97224 } 97225 97226} 97227 97228DomEventsPlugin.ɵfac = function DomEventsPlugin_Factory(t) { 97229 return new (t || DomEventsPlugin)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT)); 97230}; 97231 97232DomEventsPlugin.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 97233 token: DomEventsPlugin, 97234 factory: DomEventsPlugin.ɵfac 97235}); 97236 97237(function () { 97238 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](DomEventsPlugin, [{ 97239 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable 97240 }], function () { 97241 return [{ 97242 type: undefined, 97243 decorators: [{ 97244 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 97245 args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT] 97246 }] 97247 }]; 97248 }, null); 97249})(); 97250/** 97251 * @license 97252 * Copyright Google LLC All Rights Reserved. 97253 * 97254 * Use of this source code is governed by an MIT-style license that can be 97255 * found in the LICENSE file at https://angular.io/license 97256 */ 97257 97258/** 97259 * Defines supported modifiers for key events. 97260 */ 97261 97262 97263const MODIFIER_KEYS = ['alt', 'control', 'meta', 'shift']; // The following values are here for cross-browser compatibility and to match the W3C standard 97264// cf https://www.w3.org/TR/DOM-Level-3-Events-key/ 97265 97266const _keyMap = { 97267 '\b': 'Backspace', 97268 '\t': 'Tab', 97269 '\x7F': 'Delete', 97270 '\x1B': 'Escape', 97271 'Del': 'Delete', 97272 'Esc': 'Escape', 97273 'Left': 'ArrowLeft', 97274 'Right': 'ArrowRight', 97275 'Up': 'ArrowUp', 97276 'Down': 'ArrowDown', 97277 'Menu': 'ContextMenu', 97278 'Scroll': 'ScrollLock', 97279 'Win': 'OS' 97280}; 97281/** 97282 * Retrieves modifiers from key-event objects. 97283 */ 97284 97285const MODIFIER_KEY_GETTERS = { 97286 'alt': event => event.altKey, 97287 'control': event => event.ctrlKey, 97288 'meta': event => event.metaKey, 97289 'shift': event => event.shiftKey 97290}; 97291/** 97292 * @publicApi 97293 * A browser plug-in that provides support for handling of key events in Angular. 97294 */ 97295
97296class KeyEventsPlugin extends EventManagerPlugin { 97297 /** 97298 * Initializes an instance of the browser plug-in. 97299 * @param doc The document in which key events will be detected. 97300 */ 97301 constructor(doc) { 97302 super(doc); 97303 } 97304 /** 97305 * Reports whether a named key event is supported. 97306 * @param eventName The event name to query. 97307 * @return True if the named key event is supported. 97308 */ 97309 97310 97311 supports(eventName) { 97312 return KeyEventsPlugin.parseEventName(eventName) != null; 97313 } 97314 /** 97315 * Registers a handler for a specific element and key event. 97316 * @param element The HTML element to receive event notifications. 97317 * @param eventName The name of the key event to listen for. 97318 * @param handler A function to call when the notification occurs. Receives the 97319 * event object as an argument. 97320 * @returns The key event that was registered. 97321 */ 97322 97323 97324 addEventListener(element, eventName, handler) { 97325 const parsedEvent = KeyEventsPlugin.parseEventName(eventName); 97326 const outsideHandler = KeyEventsPlugin.eventCallback(parsedEvent['fullKey'], handler, this.manager.getZone()); 97327 return this.manager.getZone().runOutsideAngular(() => { 97328 return (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"])().onAndCancel(element, parsedEvent['domEventName'], outsideHandler); 97329 }); 97330 } 97331 /** 97332 * Parses the user provided full keyboard event definition and normalizes it for 97333 * later internal use. It ensures the string is all lowercase, converts special 97334 * characters to a standard spelling, and orders all the values consistently. 97335 * 97336 * @param eventName The name of the key event to listen for. 97337 * @returns an object with the full, normalized string, and the dom event name 97338 * or null in the case when the event doesn't match a keyboard event. 97339 */ 97340 97341 97342 static parseEventName(eventName) { 97343 const parts = eventName.toLowerCase().split('.'); 97344 const domEventName = parts.shift(); 97345 97346 if (parts.length === 0 || !(domEventName === 'keydown' || domEventName === 'keyup')) { 97347 return null; 97348 } 97349 97350 const key = KeyEventsPlugin._normalizeKey(parts.pop()); 97351 97352 let fullKey = ''; 97353 let codeIX = parts.indexOf('code'); 97354 97355 if (codeIX > -1) { 97356 parts.splice(codeIX, 1); 97357 fullKey = 'code.'; 97358 } 97359 97360 MODIFIER_KEYS.forEach(modifierName => { 97361 const index = parts.indexOf(modifierName); 97362 97363 if (index > -1) { 97364 parts.splice(index, 1); 97365 fullKey += modifierName + '.'; 97366 } 97367 }); 97368 fullKey += key; 97369 97370 if (parts.length != 0 || key.length === 0) { 97371 // returning null instead of throwing to let another plugin process the event 97372 return null; 97373 } // NOTE: Please don't rewrite this as so, as it will break JSCompiler property renaming. 97374 // The code must remain in the `result['domEventName']` form. 97375 // return {domEventName, fullKey}; 97376 97377 97378 const result = {}; 97379 result['domEventName'] = domEventName; 97380 result['fullKey'] = fullKey; 97381 return result; 97382 } 97383 /** 97384 * Determines whether the actual keys pressed match the configured key code string. 97385 * The `fullKeyCode` event is normalized in the `parseEventName` method when the 97386 * event is attached to the DOM during the `addEventListener` call. This is unseen 97387 * by the end user and is normalized for internal consistency and parsing. 97388 * 97389 * @param event The keyboard event. 97390 * @param fullKeyCode The normalized user defined expected key event string 97391 * @returns boolean. 97392 */ 97393 97394 97395 static matchEventFullKeyCode(event, fullKeyCode) { 97396 let keycode = _keyMap[event.key] || event.key; 97397 let key = ''; 97398 97399 if (fullKeyCode.indexOf('code.') > -1) { 97400 keycode = event.code; 97401 key = 'code.'; 97402 } // the keycode could be unidentified so we have to check here 97403 97404 97405 if (keycode == null || !keycode) return false; 97406 keycode = keycode.toLowerCase(); 97407 97408 if (keycode === ' ') { 97409 keycode = 'space'; // for readability 97410 } else if (keycode === '.') { 97411 keycode = 'dot'; // because '.' is used as a separator in event names 97412 } 97413 97414 MODIFIER_KEYS.forEach(modifierName => { 97415 if (modifierName !== keycode) { 97416 const modifierGetter = MODIFIER_KEY_GETTERS[modifierName]; 97417 97418 if (modifierGetter(event)) { 97419 key += modifierName + '.'; 97420 } 97421 } 97422 }); 97423 key += keycode; 97424 return key === fullKeyCode; 97425 } 97426 /** 97427 * Configures a handler callback for a key event. 97428 * @param fullKey The event name that combines all simultaneous keystrokes. 97429 * @param handler The function that responds to the key event. 97430 * @param zone The zone in which the event occurred. 97431 * @returns A callback function. 97432 */ 97433 97434 97435 static eventCallback(fullKey, handler, zone) { 97436 return event => { 97437 if (KeyEventsPlugin.matchEventFullKeyCode(event, fullKey)) { 97438 zone.runGuarded(() => handler(event)); 97439 } 97440 }; 97441 } 97442 /** @internal */ 97443 97444 97445 static _normalizeKey(keyName) { 97446 // TODO: switch to a Map if the mapping grows too much 97447 switch (keyName) { 97448 case 'esc': 97449 return 'escape'; 97450 97451 default: 97452 return keyName; 97453 } 97454 } 97455 97456} 97457 97458KeyEventsPlugin.ɵfac = function KeyEventsPlugin_Factory(t) { 97459 return new (t || KeyEventsPlugin)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT)); 97460}; 97461 97462KeyEventsPlugin.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 97463 token: KeyEventsPlugin, 97464 factory: KeyEventsPlugin.ɵfac 97465}); 97466 97467(function () { 97468 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](KeyEventsPlugin, [{ 97469 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable 97470 }], function () { 97471 return [{ 97472 type: undefined, 97473 decorators: [{ 97474 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 97475 args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT] 97476 }] 97477 }]; 97478 }, null); 97479})(); 97480/** 97481 * @license 97482 * Copyright Google LLC All Rights Reserved. 97483 * 97484 * Use of this source code is governed by an MIT-style license that can be 97485 * found in the LICENSE file at https://angular.io/license 97486 */ 97487 97488 97489const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode; 97490/** 97491 * Bootstraps an instance of an Angular application and renders a standalone component as the 97492 * application's root component. More information about standalone components can be found in [this 97493 * guide](guide/standalone-components). 97494 * 97495 * @usageNotes 97496 * The root component passed into this function *must* be a standalone one (should have the 97497 * `standalone: true` flag in the `@Component` decorator config). 97498 * 97499 * ```typescript 97500 * @Component({ 97501 * standalone: true, 97502 * template: 'Hello world!' 97503 * }) 97504 * class RootComponent {} 97505 * 97506 * const appRef: ApplicationRef = await bootstrapApplication(RootComponent); 97507 * ``` 97508 * 97509 * You can add the list of providers that should be available in the application injector by 97510 * specifying the `providers` field in an object passed as the second argument: 97511 * 97512 * ```typescript 97513 * await bootstrapApplication(RootComponent, { 97514 * providers: [ 97515 * {provide: BACKEND_URL, useValue: 'https://yourdomain.com/api'} 97516 * ] 97517 * }); 97518 * ``` 97519 * 97520 * The `importProvidersFrom` helper method can be used to collect all providers from any 97521 * existing NgModule (and transitively from all NgModules that it imports): 97522 * 97523 * ```typescript 97524 * await bootstrapApplication(RootComponent, { 97525 * providers: [ 97526 * importProvidersFrom(SomeNgModule) 97527 * ] 97528 * }); 97529 * ``` 97530 *
97531 * Note: the `bootstrapApplication` method doesn't include [Testability](api/core/Testability) by 97532 * default. You can add [Testability](api/core/Testability) by getting the list of necessary 97533 * providers using `provideProtractorTestingSupport()` function and adding them into the `providers` 97534 * array, for example: 97535 * 97536 * ```typescript 97537 * import {provideProtractorTestingSupport} from '@angular/platform-browser'; 97538 * 97539 * await bootstrapApplication(RootComponent, {providers: [provideProtractorTestingSupport()]}); 97540 * ``` 97541 * 97542 * @param rootComponent A reference to a standalone component that should be rendered. 97543 * @param options Extra configuration for the bootstrap operation, see `ApplicationConfig` for 97544 * additional info. 97545 * @returns A promise that returns an `ApplicationRef` instance once resolved. 97546 * 97547 * @publicApi 97548 * @developerPreview 97549 */ 97550 97551function bootstrapApplication(rootComponent, options) { 97552 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵinternalCreateApplication"])({ 97553 rootComponent, 97554 ...createProvidersConfig(options) 97555 }); 97556} 97557/** 97558 * Create an instance of an Angular application without bootstrapping any components. This is useful 97559 * for the situation where one wants to decouple application environment creation (a platform and 97560 * associated injectors) from rendering components on a screen. Components can be subsequently 97561 * bootstrapped on the returned `ApplicationRef`. 97562 * 97563 * @param options Extra configuration for the application environment, see `ApplicationConfig` for 97564 * additional info. 97565 * @returns A promise that returns an `ApplicationRef` instance once resolved. 97566 * 97567 * @publicApi 97568 * @developerPreview 97569 */ 97570 97571 97572function createApplication(options) { 97573 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵinternalCreateApplication"])(createProvidersConfig(options)); 97574} 97575 97576function createProvidersConfig(options) { 97577 return { 97578 appProviders: [...BROWSER_MODULE_PROVIDERS, ...(options?.providers ?? [])], 97579 platformProviders: INTERNAL_BROWSER_PLATFORM_PROVIDERS 97580 }; 97581} 97582/** 97583 * Returns a set of providers required to setup [Testability](api/core/Testability) for an 97584 * application bootstrapped using the `bootstrapApplication` function. The set of providers is 97585 * needed to support testing an application with Protractor (which relies on the Testability APIs 97586 * to be present). 97587 * 97588 * @returns An array of providers required to setup Testability for an application and make it 97589 * available for testing using Protractor. 97590 * 97591 * @developerPreview 97592 * @publicApi 97593 */ 97594 97595 97596function provideProtractorTestingSupport() { 97597 // Return a copy to prevent changes to the original array in case any in-place 97598 // alterations are performed to the `provideProtractorTestingSupport` call results in app code. 97599 return [...TESTABILITY_PROVIDERS]; 97600} 97601 97602function initDomAdapter() { 97603 BrowserDomAdapter.makeCurrent(); 97604} 97605 97606function errorHandler() { 97607 return new _angular_core__WEBPACK_IMPORTED_MODULE_1__.ErrorHandler(); 97608} 97609 97610function _document() { 97611 // Tell ivy about the global document 97612 (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetDocument"])(document); 97613 return document; 97614} 97615 97616const INTERNAL_BROWSER_PLATFORM_PROVIDERS = [{ 97617 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.PLATFORM_ID, 97618 useValue: _angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵPLATFORM_BROWSER_ID"] 97619}, { 97620 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.PLATFORM_INITIALIZER, 97621 useValue: initDomAdapter, 97622 multi: true 97623}, { 97624 provide: _angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT, 97625 useFactory: _document, 97626 deps: [] 97627}]; 97628/** 97629 * A factory function that returns a `PlatformRef` instance associated with browser service 97630 * providers. 97631 * 97632 * @publicApi 97633 */ 97634 97635const platformBrowser = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.createPlatformFactory)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.platformCore, 'browser', INTERNAL_BROWSER_PLATFORM_PROVIDERS); 97636/** 97637 * Internal marker to signal whether providers from the `BrowserModule` are already present in DI. 97638 * This is needed to avoid loading `BrowserModule` providers twice. We can't rely on the 97639 * `BrowserModule` presence itself, since the standalone-based bootstrap just imports 97640 * `BrowserModule` providers without referencing the module itself. 97641 */ 97642 97643const BROWSER_MODULE_PROVIDERS_MARKER = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken(NG_DEV_MODE ? 'BrowserModule Providers Marker' : ''); 97644const TESTABILITY_PROVIDERS = [{ 97645 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵTESTABILITY_GETTER"], 97646 useClass: BrowserGetTestability, 97647 deps: [] 97648}, { 97649 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵTESTABILITY"], 97650 useClass: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Testability, 97651 deps: [_angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone, _angular_core__WEBPACK_IMPORTED_MODULE_1__.TestabilityRegistry, _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵTESTABILITY_GETTER"]
97651] 97652}, { 97653 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Testability, 97654 useClass: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Testability, 97655 deps: [_angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone, _angular_core__WEBPACK_IMPORTED_MODULE_1__.TestabilityRegistry, _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵTESTABILITY_GETTER"]] 97656}]; 97657const BROWSER_MODULE_PROVIDERS = [{ 97658 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵINJECTOR_SCOPE"], 97659 useValue: 'root' 97660}, { 97661 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.ErrorHandler, 97662 useFactory: errorHandler, 97663 deps: [] 97664}, { 97665 provide: EVENT_MANAGER_PLUGINS, 97666 useClass: DomEventsPlugin, 97667 multi: true, 97668 deps: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT, _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone, _angular_core__WEBPACK_IMPORTED_MODULE_1__.PLATFORM_ID] 97669}, { 97670 provide: EVENT_MANAGER_PLUGINS, 97671 useClass: KeyEventsPlugin, 97672 multi: true, 97673 deps: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT] 97674}, { 97675 provide: DomRendererFactory2, 97676 useClass: DomRendererFactory2, 97677 deps: [EventManager, DomSharedStylesHost, _angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_ID] 97678}, { 97679 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.RendererFactory2, 97680 useExisting: DomRendererFactory2 97681}, { 97682 provide: SharedStylesHost, 97683 useExisting: DomSharedStylesHost 97684}, { 97685 provide: DomSharedStylesHost, 97686 useClass: DomSharedStylesHost, 97687 deps: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT] 97688}, { 97689 provide: EventManager, 97690 useClass: EventManager, 97691 deps: [EVENT_MANAGER_PLUGINS, _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgZone] 97692}, { 97693 provide: _angular_common__WEBPACK_IMPORTED_MODULE_0__.XhrFactory, 97694 useClass: BrowserXhr, 97695 deps: [] 97696}, NG_DEV_MODE ? { 97697 provide: BROWSER_MODULE_PROVIDERS_MARKER, 97698 useValue: true 97699} : []]; 97700/** 97701 * Exports required infrastructure for all Angular apps. 97702 * Included by default in all Angular apps created with the CLI 97703 * `new` command. 97704 * Re-exports `CommonModule` and `ApplicationModule`, making their 97705 * exports and providers available to all apps. 97706 * 97707 * @publicApi 97708 */ 97709 97710class BrowserModule { 97711 constructor(providersAlreadyPresent) { 97712 if (NG_DEV_MODE && providersAlreadyPresent) { 97713 throw new Error(`Providers from the \`BrowserModule\` have already been loaded. If you need access ` + `to common directives such as NgIf and NgFor, import the \`CommonModule\` instead.`); 97714 } 97715 } 97716 /** 97717 * Configures a browser-based app to transition from a server-rendered app, if 97718 * one is present on the page. 97719 * 97720 * @param params An object containing an identifier for the app to transition. 97721 * The ID must match between the client and server versions of the app. 97722 * @returns The reconfigured `BrowserModule` to import into the app's root `AppModule`. 97723 */ 97724 97725 97726 static withServerTransition(params) { 97727 return { 97728 ngModule: BrowserModule, 97729 providers: [{ 97730 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_ID, 97731 useValue: params.appId 97732 }, { 97733 provide: TRANSITION_ID, 97734 useExisting: _angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_ID 97735 }, SERVER_TRANSITION_PROVIDERS] 97736 }; 97737 } 97738 97739} 97740 97741BrowserModule.ɵfac = function BrowserModule_Factory(t) { 97742 return new (t || BrowserModule)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](BROWSER_MODULE_PROVIDERS_MARKER, 12)); 97743}; 97744 97745BrowserModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineNgModule"]({ 97746 type: BrowserModule, 97747 exports: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.CommonModule, _angular_core__WEBPACK_IMPORTED_MODULE_1__.ApplicationModule] 97748}); 97749BrowserModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjector"]({ 97750 providers: [...BROWSER_MODULE_PROVIDERS, ...TESTABILITY_PROVIDERS], 97751 imports: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.CommonModule, _angular_core__WEBPACK_IMPORTED_MODULE_1__.ApplicationModule] 97752}); 97753 97754(function () { 97755 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](BrowserModule, [{ 97756 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgModule, 97757 args: [{ 97758 providers: [...BROWSER_MODULE_PROVIDERS, ...TESTABILITY_PROVIDERS], 97759 exports: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.CommonModule, _angular_core__WEBPACK_IMPORTED_MODULE_1__.ApplicationModule] 97760 }] 97761 }], function () { 97762 return [{ 97763 type: undefined, 97764 decorators: [{ 97765 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional 97766 }, { 97767 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.SkipSelf 97768 }, { 97769 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 97770 args: [BROWSER_MODULE_PROVIDERS_MARKER] 97771 }] 97772 }]; 97773 }, null); 97774})(); 97775/** 97776 * @license 97777 * Copyright Google LLC All Rights Reserved. 97778 * 97779 * Use of this source code is governed by an MIT-style license that can be 97780 * found in the LICENSE file at https://angular.io/license 97781 */ 97782 97783/** 97784 * Factory to create a `Meta` service instance for the current DOM document. 97785 */ 97786 97787 97788function createMeta() { 97789 return new Meta((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT)); 97790} 97791/** 97792 * A service for managing HTML `<meta>` tags. 97793 * 97794 * Properties of the `MetaDefinition` object match the attributes of the 97795 * HTML `<meta>` tag. These tags define document metadata that is important for 97796 * things like configuring a Content Security Policy, defining browser compatibility 97797 * and security settings, setting HTTP Headers, defining rich content for social sharing, 97798 * and Search Engine Optimization (SEO). 97799 * 97800 * To identify specific `<meta>` tags in a document, use an attribute selection 97801 * string in the format `"tag_attribute='value string'"`. 97802 * For example, an `attrSelector` value of `"name='description'"` matches a tag 97803 * whose `name` attribute has the value `"description"`. 97804 * Selectors are used with the `querySelector()` Document method, 97805 * in the format `meta[{attrSelector}]`. 97806 * 97807 * @see [HTML meta tag](https://developer.mozilla.org/docs/Web/HTML/Element/meta) 97808 * @see [Document.querySelector()](https://developer.mozilla.org/docs/Web/API/Document/querySelector) 97809 * 97810 * 97811 * @publicApi 97812 */ 97813 97814 97815class Meta { 97816 constructor(_doc) { 97817 this._doc = _doc; 97818 this._dom = (0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"])(); 97819 } 97820 /** 97821 * Retrieves or creates a specific `<meta>` tag element in the current HTML document. 97822 * In searching for an existing tag, Angular attempts to match the `name` or `property` attribute 97823 * values in the provided tag definition, and verifies that all other attribute values are equal. 97824 * If an existing element is found, it is returned and is not modified in any way. 97825 * @param tag The definition of a `<meta>` element to match or create. 97826 * @param forceCreation True to create a new element without checking whether one already exists. 97827 * @returns The existing element with the same attributes and values if found, 97828 * the new element if no match is found, or `null` if the tag parameter is not defined. 97829 */ 97830 97831 97832 addTag(tag, forceCreation = false) { 97833 if (!tag) return null; 97834 return this._getOrCreateElement(tag, forceCreation); 97835 } 97836 /** 97837 * Retrieves or creates a set of `<meta>` tag elements in the current HTML document. 97838 * In searching for an existing tag, Angular attempts to match the `name` or `property` attribute 97839 * values in the provided tag definition, and verifies that all other attribute values are equal. 97840 * @param tags An array of tag definitions to match or create. 97841 * @param forceCreation True to create new elements without checking whether they already exist. 97842 * @returns The matching elements if found, or the new elements. 97843 */ 97844 97845 97846 addTags(tags, forceCreation = false) { 97847 if (!tags) return []; 97848 return tags.reduce((result, tag) => { 97849 if (tag) { 97850 result.push(this._getOrCreateElement(tag, forceCreation)); 97851 } 97852 97853 return result; 97854 }, []); 97855 } 97856 /** 97857 * Retrieves a `<meta>` tag element in the current HTML document. 97858 * @param attrSelector The tag attribute and value to match against, in the format 97859 * `"tag_attribute='value string'"`. 97860 * @returns The matching element, if any. 97861 */ 97862 97863 97864 getTag(attrSelector) { 97865 if (!attrSelector) return null; 97866 return this._doc.querySelector(`meta[${attrSelector}]`) || null; 97867 } 97868 /** 97869 * Retrieves a set of `<meta>` tag elements in the current HTML document. 97870 * @param attrSelector The tag attribute and value to match against, in the format 97871 * `"tag_attribute='value string'"`. 97872 * @returns The matching elements, if any. 97873 */ 97874 97875 97876 getTags(attrSelector) { 97877 if (!attrSelector) return []; 97878 97879 const list 97880 /*NodeList*/ 97881 = this._doc.querySelectorAll(`meta[${attrSelector}]`); 97882 97883 return list ? [].slice.call(list) : []; 97884 } 97885 /** 97886 * Modifies an existing `<meta>` tag element in the current HTML document. 97887 * @param tag The tag description with which to replace the existing tag content. 97888 * @param selector A tag attribute and value to match against, to identify 97889 * an existing tag. A string in the format `"tag_attribute=`value string`"`. 97890 * If not supplied, matches a tag with the same `name` or `property` attribute value as the 97891 * replacement tag. 97892 * @return The modified element. 97893 */ 97894 97895 97896 updateTag(tag, selector) { 97897 if (!tag) return null; 97898 selector = selector || this._parseSelector(tag); 97899 const meta = this.getTag(selector); 97900 97901 if (meta) { 97902 return this._setMetaElementAttributes(tag, meta); 97903 } 97904 97905 return this._getOrCreateElement(tag, true); 97906 } 97907 /** 97908 * Removes an existing `<meta>` tag element from the current HTML document. 97909 * @param attrSelector A tag attribute and value to match against, to identify 97910 * an existing tag. A string in the format `"tag_attribute=`value string`"`. 97911 */ 97912 97913
97914 removeTag(attrSelector) { 97915 this.removeTagElement(this.getTag(attrSelector)); 97916 } 97917 /** 97918 * Removes an existing `<meta>` tag element from the current HTML document. 97919 * @param meta The tag definition to match against to identify an existing tag. 97920 */ 97921 97922 97923 removeTagElement(meta) { 97924 if (meta) { 97925 this._dom.remove(meta); 97926 } 97927 } 97928 97929 _getOrCreateElement(meta, forceCreation = false) { 97930 if (!forceCreation) { 97931 const selector = this._parseSelector(meta); // It's allowed to have multiple elements with the same name so it's not enough to 97932 // just check that element with the same name already present on the page. We also need to 97933 // check if element has tag attributes 97934 97935 97936 const elem = this.getTags(selector).filter(elem => this._containsAttributes(meta, elem))[0]; 97937 if (elem !== undefined) return elem; 97938 } 97939 97940 const element = this._dom.createElement('meta'); 97941 97942 this._setMetaElementAttributes(meta, element); 97943 97944 const head = this._doc.getElementsByTagName('head')[0]; 97945 97946 head.appendChild(element); 97947 return element; 97948 } 97949 97950 _setMetaElementAttributes(tag, el) { 97951 Object.keys(tag).forEach(prop => el.setAttribute(this._getMetaKeyMap(prop), tag[prop])); 97952 return el; 97953 } 97954 97955 _parseSelector(tag) { 97956 const attr = tag.name ? 'name' : 'property'; 97957 return `${attr}="${tag[attr]}"`; 97958 } 97959 97960 _containsAttributes(tag, elem) { 97961 return Object.keys(tag).every(key => elem.getAttribute(this._getMetaKeyMap(key)) === tag[key]); 97962 } 97963 97964 _getMetaKeyMap(prop) { 97965 return META_KEYS_MAP[prop] || prop; 97966 } 97967 97968} 97969 97970Meta.ɵfac = function Meta_Factory(t) { 97971 return new (t || Meta)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT)); 97972}; 97973 97974Meta.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 97975 token: Meta, 97976 factory: function Meta_Factory(t) { 97977 let r = null; 97978 97979 if (t) { 97980 r = new t(); 97981 } else { 97982 r = createMeta(); 97983 } 97984 97985 return r; 97986 }, 97987 providedIn: 'root' 97988}); 97989 97990(function () { 97991 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](Meta, [{ 97992 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable, 97993 args: [{ 97994 providedIn: 'root', 97995 useFactory: createMeta, 97996 deps: [] 97997 }] 97998 }], function () { 97999 return [{ 98000 type: undefined, 98001 decorators: [{ 98002 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 98003 args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT] 98004 }] 98005 }]; 98006 }, null); 98007})(); 98008/** 98009 * Mapping for MetaDefinition properties with their correct meta attribute names 98010 */ 98011 98012 98013const META_KEYS_MAP = { 98014 httpEquiv: 'http-equiv' 98015}; 98016/** 98017 * @license 98018 * Copyright Google LLC All Rights Reserved. 98019 * 98020 * Use of this source code is governed by an MIT-style license that can be 98021 * found in the LICENSE file at https://angular.io/license 98022 */ 98023 98024/** 98025 * Factory to create Title service. 98026 */ 98027 98028function createTitle() { 98029 return new Title((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT)); 98030} 98031/** 98032 * A service that can be used to get and set the title of a current HTML document. 98033 * 98034 * Since an Angular application can't be bootstrapped on the entire HTML document (`<html>` tag) 98035 * it is not possible to bind to the `text` property of the `HTMLTitleElement` elements 98036 * (representing the `<title>` tag). Instead, this service can be used to set and get the current 98037 * title value. 98038 * 98039 * @publicApi 98040 */ 98041 98042 98043class Title { 98044 constructor(_doc) { 98045 this._doc = _doc; 98046 } 98047 /** 98048 * Get the title of the current HTML document. 98049 */ 98050 98051 98052 getTitle() { 98053 return this._doc.title; 98054 } 98055 /** 98056 * Set the title of the current HTML document. 98057 * @param newTitle 98058 */ 98059 98060 98061 setTitle(newTitle) { 98062 this._doc.title = newTitle || ''; 98063 } 98064 98065} 98066 98067Title.ɵfac = function Title_Factory(t) { 98068 return new (t || Title)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT)); 98069}; 98070 98071Title.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 98072 token: Title, 98073 factory: function Title_Factory(t) { 98074 let r = null; 98075 98076 if (t) { 98077 r = new t(); 98078 } else { 98079 r = createTitle(); 98080 } 98081 98082 return r; 98083 }, 98084 providedIn: 'root' 98085}); 98086 98087(function () { 98088 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](Title, [{ 98089 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable, 98090 args: [{ 98091 providedIn: 'root', 98092 useFactory: createTitle, 98093 deps: [] 98094 }] 98095 }], function () { 98096 return [{ 98097 type: undefined, 98098 decorators: [{ 98099 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 98100 args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT] 98101 }] 98102 }]; 98103 }, null); 98104})(); 98105/** 98106 * @license 98107 * Copyright Google LLC All Rights Reserved. 98108 * 98109 * Use of this source code is governed by an MIT-style license that can be 98110 * found in the LICENSE file at https://angular.io/license 98111 */ 98112 98113 98114const CAMEL_CASE_REGEXP = /([A-Z])/g; 98115const DASH_CASE_REGEXP = /-([a-z])/g; 98116 98117function camelCaseToDashCase(input) { 98118 return input.replace(CAMEL_CASE_REGEXP, (...m) => '-' + m[1].toLowerCase()); 98119} 98120 98121function dashCaseToCamelCase(input) { 98122 return input.replace(DASH_CASE_REGEXP, (...m) => m[1].toUpperCase()); 98123} 98124/** 98125 * Exports the value under a given `name` in the global property `ng`. For example `ng.probe` if 98126 * `name` is `'probe'`. 98127 * @param name Name under which it will be exported. Keep in mind this will be a property of the 98128 * global `ng` object. 98129 * @param value The value to export. 98130 */ 98131 98132 98133function exportNgVar(name, value) { 98134 if (typeof COMPILED === 'undefined' || !COMPILED) { 98135 // Note: we can't export `ng` when using closure enhanced optimization as: 98136 // - closure declares globals itself for minified names, which sometimes clobber our `ng` global 98137 // - we can't declare a closure extern as the namespace `ng` is already used within Google 98138 // for typings for angularJS (via `goog.provide('ng....')`). 98139 const ng = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].ng = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵglobal"].ng || {}; 98140 ng[name] = value; 98141 } 98142} 98143/** 98144 * @license 98145 * Copyright Google LLC All Rights Reserved. 98146 * 98147 * Use of this source code is governed by an MIT-style license that can be 98148 * found in the LICENSE file at https://angular.io/license 98149 */ 98150 98151 98152const win = typeof window !== 'undefined' && window || {}; 98153/** 98154 * @license 98155 * Copyright Google LLC All Rights Reserved. 98156 * 98157 * Use of this source code is governed by an MIT-style license that can be 98158 * found in the LICENSE file at https://angular.io/license 98159 */ 98160 98161class ChangeDetectionPerfRecord { 98162 constructor(msPerTick, numTicks) { 98163 this.msPerTick = msPerTick; 98164 this.numTicks = numTicks; 98165 } 98166 98167} 98168/** 98169 * Entry point for all Angular profiling-related debug tools. This object 98170 * corresponds to the `ng.profiler` in the dev console. 98171 */ 98172 98173 98174class AngularProfiler {
98175 constructor(ref) { 98176 this.appRef = ref.injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_1__.ApplicationRef); 98177 } // tslint:disable:no-console 98178 98179 /** 98180 * Exercises change detection in a loop and then prints the average amount of 98181 * time in milliseconds how long a single round of change detection takes for 98182 * the current state of the UI. It runs a minimum of 5 rounds for a minimum 98183 * of 500 milliseconds. 98184 * 98185 * Optionally, a user may pass a `config` parameter containing a map of 98186 * options. Supported options are: 98187 * 98188 * `record` (boolean) - causes the profiler to record a CPU profile while 98189 * it exercises the change detector. Example: 98190 * 98191 * ``` 98192 * ng.profiler.timeChangeDetection({record: true}) 98193 * ``` 98194 */ 98195 98196 98197 timeChangeDetection(config) { 98198 const record = config && config['record']; 98199 const profileName = 'Change Detection'; // Profiler is not available in Android browsers without dev tools opened 98200 98201 const isProfilerAvailable = win.console.profile != null; 98202 98203 if (record && isProfilerAvailable) { 98204 win.console.profile(profileName); 98205 } 98206 98207 const start = performanceNow(); 98208 let numTicks = 0; 98209 98210 while (numTicks < 5 || performanceNow() - start < 500) { 98211 this.appRef.tick(); 98212 numTicks++; 98213 } 98214 98215 const end = performanceNow(); 98216 98217 if (record && isProfilerAvailable) { 98218 win.console.profileEnd(profileName); 98219 } 98220 98221 const msPerTick = (end - start) / numTicks; 98222 win.console.log(`ran ${numTicks} change detection cycles`); 98223 win.console.log(`${msPerTick.toFixed(2)} ms per check`); 98224 return new ChangeDetectionPerfRecord(msPerTick, numTicks); 98225 } 98226 98227} 98228 98229function performanceNow() { 98230 return win.performance && win.performance.now ? win.performance.now() : new Date().getTime(); 98231} 98232/** 98233 * @license 98234 * Copyright Google LLC All Rights Reserved. 98235 * 98236 * Use of this source code is governed by an MIT-style license that can be 98237 * found in the LICENSE file at https://angular.io/license 98238 */ 98239 98240 98241const PROFILER_GLOBAL_NAME = 'profiler'; 98242/** 98243 * Enabled Angular debug tools that are accessible via your browser's 98244 * developer console. 98245 * 98246 * Usage: 98247 * 98248 * 1. Open developer console (e.g. in Chrome Ctrl + Shift + j) 98249 * 1. Type `ng.` (usually the console will show auto-complete suggestion) 98250 * 1. Try the change detection profiler `ng.profiler.timeChangeDetection()` 98251 * then hit Enter. 98252 * 98253 * @publicApi 98254 */ 98255 98256function enableDebugTools(ref) { 98257 exportNgVar(PROFILER_GLOBAL_NAME, new AngularProfiler(ref)); 98258 return ref; 98259} 98260/** 98261 * Disables Angular tools. 98262 * 98263 * @publicApi 98264 */ 98265 98266 98267function disableDebugTools() { 98268 exportNgVar(PROFILER_GLOBAL_NAME, null); 98269} 98270/** 98271 * @license 98272 * Copyright Google LLC All Rights Reserved. 98273 * 98274 * Use of this source code is governed by an MIT-style license that can be 98275 * found in the LICENSE file at https://angular.io/license 98276 */ 98277 98278 98279function escapeHtml(text) { 98280 const escapedText = { 98281 '&': '&a;', 98282 '"': '&q;', 98283 '\'': '&s;', 98284 '<': '&l;', 98285 '>': '&g;' 98286 }; 98287 return text.replace(/[&"'<>]/g, s => escapedText[s]); 98288} 98289 98290function unescapeHtml(text) { 98291 const unescapedText = { 98292 '&a;': '&', 98293 '&q;': '"', 98294 '&s;': '\'', 98295 '&l;': '<', 98296 '&g;': '>' 98297 }; 98298 return text.replace(/&[^;]+;/g, s => unescapedText[s]); 98299} 98300/** 98301 * Create a `StateKey<T>` that can be used to store value of type T with `TransferState`. 98302 * 98303 * Example: 98304 * 98305 * ``` 98306 * const COUNTER_KEY = makeStateKey<number>('counter'); 98307 * let value = 10; 98308 * 98309 * transferState.set(COUNTER_KEY, value); 98310 * ``` 98311 * 98312 * @publicApi 98313 */ 98314 98315 98316function makeStateKey(key) { 98317 return key; 98318} 98319/** 98320 * A key value store that is transferred from the application on the server side to the application 98321 * on the client side. 98322 * 98323 * The `TransferState` is available as an injectable token. 98324 * On the client, just inject this token using DI and use it, it will be lazily initialized. 98325 * On the server it's already included if `renderApplication` function is used. Otherwise, import 98326 * the `ServerTransferStateModule` module to make the `TransferState` available. 98327 * 98328 * The values in the store are serialized/deserialized using JSON.stringify/JSON.parse. So only 98329 * boolean, number, string, null and non-class objects will be serialized and deserialized in a 98330 * non-lossy manner. 98331 * 98332 * @publicApi 98333 */ 98334 98335 98336class TransferState { 98337 constructor() { 98338 this.store = {}; 98339 this.onSerializeCallbacks = {}; 98340 } 98341 /** 98342 * Get the value corresponding to a key. Return `defaultValue` if key is not found. 98343 */ 98344 98345 98346 get(key, defaultValue) { 98347 return this.store[key] !== undefined ? this.store[key] : defaultValue; 98348 } 98349 /** 98350 * Set the value corresponding to a key. 98351 */ 98352 98353 98354 set(key, value) { 98355 this.store[key] = value; 98356 } 98357 /** 98358 * Remove a key from the store. 98359 */ 98360 98361 98362 remove(key) { 98363 delete this.store[key]; 98364 } 98365 /** 98366 * Test whether a key exists in the store. 98367 */ 98368 98369 98370 hasKey(key) { 98371 return this.store.hasOwnProperty(key); 98372 } 98373 /** 98374 * Indicates whether the state is empty. 98375 */ 98376 98377 98378 get isEmpty() { 98379 return Object.keys(this.store).length === 0; 98380 } 98381 /** 98382 * Register a callback to provide the value for a key when `toJson` is called. 98383 */ 98384 98385 98386 onSerialize(key, callback) { 98387 this.onSerializeCallbacks[key] = callback; 98388 } 98389 /** 98390 * Serialize the current state of the store to JSON. 98391 */ 98392 98393 98394 toJson() { 98395 // Call the onSerialize callbacks and put those values into the store. 98396 for (const key in this.onSerializeCallbacks) { 98397 if (this.onSerializeCallbacks.hasOwnProperty(key)) { 98398 try { 98399 this.store[key] = this.onSerializeCallbacks[key](); 98400 } catch (e) { 98401 console.warn('Exception in onSerialize callback: ', e); 98402 } 98403 } 98404 } 98405 98406 return JSON.stringify(this.store); 98407 } 98408 98409} 98410 98411TransferState.ɵfac = function TransferState_Factory(t) { 98412 return new (t || TransferState)(); 98413}; 98414 98415TransferState.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 98416 token: TransferState, 98417 factory: function () { 98418 return (() => { 98419 const doc = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT); 98420 const appId = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_ID); 98421 const state = new TransferState(); 98422 state.store = retrieveTransferredState(doc, appId); 98423 return state; 98424 })(); 98425 }, 98426 providedIn: 'root' 98427}); 98428 98429(function () { 98430 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](TransferState, [{ 98431 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable, 98432 args: [{ 98433 providedIn: 'root', 98434 useFactory: () => { 98435 const doc = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT); 98436 const appId = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_ID); 98437 const state = new TransferState(); 98438 state.store = retrieveTransferredState(doc, appId); 98439 return state; 98440 } 98441 }] 98442 }], null, null); 98443})(); 98444 98445function retrieveTransferredState(doc, appId) { 98446 // Locate the script tag with the JSON data transferred from the server. 98447 // The id of the script tag is set to the Angular appId + 'state'. 98448 const script = doc.getElementById(appId + '-state'); 98449 let initialState = {}; 98450 98451 if (script && script.textContent) { 98452 try { 98453 // Avoid using any here as it triggers lint errors in google3 (any is not allowed). 98454 initialState = JSON.parse(unescapeHtml(script.textContent)); 98455 } catch (e) { 98456 console.warn('Exception while restoring TransferState for app ' + appId, e); 98457 } 98458 } 98459 98460 return initialState; 98461} 98462/** 98463 * NgModule to install on the client side while using the `TransferState` to transfer state from 98464 * server to client. 98465 * 98466 * @publicApi 98467 * @deprecated no longer needed, you can inject the `TransferState` in an app without providing 98468 * this module. 98469 */ 98470 98471 98472class BrowserTransferStateModule {} 98473 98474BrowserTransferStateModule.ɵfac = function BrowserTransferStateModule_Factory(t) { 98475 return new (t || BrowserTransferStateModule)(); 98476}; 98477 98478BrowserTransferStateModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineNgModule"]({ 98479 type: BrowserTransferStateModule 98480}); 98481BrowserTransferStateModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjector"]({}); 98482 98483(function () { 98484 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](BrowserTransferStateModule, [{ 98485 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgModule, 98486 args: [{}] 98487 }], null, null); 98488})(); 98489/** 98490 * @license 98491 * Copyright Google LLC All Rights Reserved. 98492 * 98493 * Use of this source code is governed by an MIT-style license that can be 98494 * found in the LICENSE file at https://angular.io/license 98495 */ 98496 98497/** 98498 * Predicates for use with {@link DebugElement}'s query functions. 98499 * 98500 * @publicApi 98501 */ 98502 98503 98504class By { 98505 /** 98506 * Match all nodes. 98507 * 98508 * @usageNotes 98509 * ### Example 98510 * 98511 * {@example platform-browser/dom/debug/ts/by/by.ts region='by_all'} 98512 */ 98513 static all() { 98514 return () => true; 98515 } 98516 /** 98517 * Match elements by the given CSS selector. 98518 * 98519 * @usageNotes 98520 * ### Example 98521 * 98522 * {@example platform-browser/dom/debug/ts/by/by.ts region='by_css'} 98523 */ 98524 98525 98526 static css(selector) { 98527 return debugElement => { 98528 return debugElement.nativeElement != null ? elementMatches(debugElement.nativeElement, selector) : false;
98529 }; 98530 } 98531 /** 98532 * Match nodes that have the given directive present. 98533 * 98534 * @usageNotes 98535 * ### Example 98536 * 98537 * {@example platform-browser/dom/debug/ts/by/by.ts region='by_directive'} 98538 */ 98539 98540 98541 static directive(type) { 98542 return debugNode => debugNode.providerTokens.indexOf(type) !== -1; 98543 } 98544 98545} 98546 98547function elementMatches(n, selector) { 98548 if ((0,_angular_common__WEBPACK_IMPORTED_MODULE_0__["ɵgetDOM"])().isElementNode(n)) { 98549 return n.matches && n.matches(selector) || n.msMatchesSelector && n.msMatchesSelector(selector) || n.webkitMatchesSelector && n.webkitMatchesSelector(selector); 98550 } 98551 98552 return false; 98553} 98554/** 98555 * @license 98556 * Copyright Google LLC All Rights Reserved. 98557 * 98558 * Use of this source code is governed by an MIT-style license that can be 98559 * found in the LICENSE file at https://angular.io/license 98560 */ 98561 98562/** 98563 * Supported HammerJS recognizer event names. 98564 */ 98565 98566 98567const EVENT_NAMES = { 98568 // pan 98569 'pan': true, 98570 'panstart': true, 98571 'panmove': true, 98572 'panend': true, 98573 'pancancel': true, 98574 'panleft': true, 98575 'panright': true, 98576 'panup': true, 98577 'pandown': true, 98578 // pinch 98579 'pinch': true, 98580 'pinchstart': true, 98581 'pinchmove': true, 98582 'pinchend': true, 98583 'pinchcancel': true, 98584 'pinchin': true, 98585 'pinchout': true, 98586 // press 98587 'press': true, 98588 'pressup': true, 98589 // rotate 98590 'rotate': true, 98591 'rotatestart': true, 98592 'rotatemove': true, 98593 'rotateend': true, 98594 'rotatecancel': true, 98595 // swipe 98596 'swipe': true, 98597 'swipeleft': true, 98598 'swiperight': true, 98599 'swipeup': true, 98600 'swipedown': true, 98601 // tap 98602 'tap': true, 98603 'doubletap': true 98604}; 98605/** 98606 * DI token for providing [HammerJS](https://hammerjs.github.io/) support to Angular. 98607 * @see `HammerGestureConfig` 98608 * 98609 * @ngModule HammerModule 98610 * @publicApi 98611 */ 98612 98613const HAMMER_GESTURE_CONFIG = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('HammerGestureConfig'); 98614/** 98615 * Injection token used to provide a {@link HammerLoader} to Angular. 98616 * 98617 * @publicApi 98618 */ 98619 98620const HAMMER_LOADER = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('HammerLoader'); 98621/** 98622 * An injectable [HammerJS Manager](https://hammerjs.github.io/api/#hammermanager) 98623 * for gesture recognition. Configures specific event recognition. 98624 * @publicApi 98625 */ 98626 98627class HammerGestureConfig { 98628 constructor() { 98629 /** 98630 * A set of supported event names for gestures to be used in Angular. 98631 * Angular supports all built-in recognizers, as listed in 98632 * [HammerJS documentation](https://hammerjs.github.io/). 98633 */ 98634 this.events = []; 98635 /** 98636 * Maps gesture event names to a set of configuration options 98637 * that specify overrides to the default values for specific properties. 98638 * 98639 * The key is a supported event name to be configured, 98640 * and the options object contains a set of properties, with override values 98641 * to be applied to the named recognizer event. 98642 * For example, to disable recognition of the rotate event, specify 98643 * `{"rotate": {"enable": false}}`. 98644 * 98645 * Properties that are not present take the HammerJS default values. 98646 * For information about which properties are supported for which events, 98647 * and their allowed and default values, see 98648 * [HammerJS documentation](https://hammerjs.github.io/). 98649 * 98650 */ 98651 98652 this.overrides = {}; 98653 } 98654 /** 98655 * Creates a [HammerJS Manager](https://hammerjs.github.io/api/#hammermanager) 98656 * and attaches it to a given HTML element. 98657 * @param element The element that will recognize gestures. 98658 * @returns A HammerJS event-manager object. 98659 */ 98660 98661 98662 buildHammer(element) { 98663 const mc = new Hammer(element, this.options); 98664 mc.get('pinch').set({ 98665 enable: true 98666 }); 98667 mc.get('rotate').set({ 98668 enable: true 98669 }); 98670 98671 for (const eventName in this.overrides) { 98672 mc.get(eventName).set(this.overrides[eventName]); 98673 } 98674 98675 return mc; 98676 } 98677 98678} 98679 98680HammerGestureConfig.ɵfac = function HammerGestureConfig_Factory(t) { 98681 return new (t || HammerGestureConfig)(); 98682}; 98683 98684HammerGestureConfig.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 98685 token: HammerGestureConfig, 98686 factory: HammerGestureConfig.ɵfac 98687}); 98688 98689(function () { 98690 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](HammerGestureConfig, [{ 98691 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable 98692 }], null, null); 98693})(); 98694/** 98695 * Event plugin that adds Hammer support to an application. 98696 * 98697 * @ngModule HammerModule 98698 */ 98699 98700
98701class HammerGesturesPlugin extends EventManagerPlugin { 98702 constructor(doc, _config, console, loader) { 98703 super(doc); 98704 this._config = _config; 98705 this.console = console; 98706 this.loader = loader; 98707 this._loaderPromise = null; 98708 } 98709 98710 supports(eventName) { 98711 if (!EVENT_NAMES.hasOwnProperty(eventName.toLowerCase()) && !this.isCustomEvent(eventName)) { 98712 return false; 98713 } 98714 98715 if (!window.Hammer && !this.loader) { 98716 if (typeof ngDevMode === 'undefined' || ngDevMode) { 98717 this.console.warn(`The "${eventName}" event cannot be bound because Hammer.JS is not ` + `loaded and no custom loader has been specified.`); 98718 } 98719 98720 return false; 98721 } 98722 98723 return true; 98724 } 98725 98726 addEventListener(element, eventName, handler) { 98727 const zone = this.manager.getZone(); 98728 eventName = eventName.toLowerCase(); // If Hammer is not present but a loader is specified, we defer adding the event listener 98729 // until Hammer is loaded. 98730 98731 if (!window.Hammer && this.loader) { 98732 this._loaderPromise = this._loaderPromise || zone.runOutsideAngular(() => this.loader()); // This `addEventListener` method returns a function to remove the added listener. 98733 // Until Hammer is loaded, the returned function needs to *cancel* the registration rather 98734 // than remove anything. 98735 98736 let cancelRegistration = false; 98737 98738 let deregister = () => { 98739 cancelRegistration = true; 98740 }; 98741 98742 zone.runOutsideAngular(() => this._loaderPromise.then(() => { 98743 // If Hammer isn't actually loaded when the custom loader resolves, give up. 98744 if (!window.Hammer) { 98745 if (typeof ngDevMode === 'undefined' || ngDevMode) { 98746 this.console.warn(`The custom HAMMER_LOADER completed, but Hammer.JS is not present.`); 98747 } 98748 98749 deregister = () => {}; 98750 98751 return; 98752 } 98753 98754 if (!cancelRegistration) { 98755 // Now that Hammer is loaded and the listener is being loaded for real, 98756 // the deregistration function changes from canceling registration to 98757 // removal. 98758 deregister = this.addEventListener(element, eventName, handler); 98759 } 98760 }).catch(() => { 98761 if (typeof ngDevMode === 'undefined' || ngDevMode) { 98762 this.console.warn(`The "${eventName}" event cannot be bound because the custom ` + `Hammer.JS loader failed.`); 98763 } 98764 98765 deregister = () => {}; 98766 })); // Return a function that *executes* `deregister` (and not `deregister` itself) so that we 98767 // can change the behavior of `deregister` once the listener is added. Using a closure in 98768 // this way allows us to avoid any additional data structures to track listener removal. 98769 98770 return () => { 98771 deregister(); 98772 }; 98773 } 98774 98775 return zone.runOutsideAngular(() => { 98776 // Creating the manager bind events, must be done outside of angular 98777 const mc = this._config.buildHammer(element); 98778 98779 const callback = function (eventObj) { 98780 zone.runGuarded(function () { 98781 handler(eventObj); 98782 }); 98783 }; 98784 98785 mc.on(eventName, callback); 98786 return () => { 98787 mc.off(eventName, callback); // destroy mc to prevent memory leak 98788 98789 if (typeof mc.destroy === 'function') { 98790 mc.destroy(); 98791 } 98792 }; 98793 }); 98794 } 98795 98796 isCustomEvent(eventName) { 98797 return this._config.events.indexOf(eventName) > -1; 98798 } 98799 98800} 98801 98802HammerGesturesPlugin.ɵfac = function HammerGesturesPlugin_Factory(t) { 98803 return new (t || HammerGesturesPlugin)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](HAMMER_GESTURE_CONFIG), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵConsole"]), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](HAMMER_LOADER, 8)); 98804}; 98805 98806HammerGesturesPlugin.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 98807 token: HammerGesturesPlugin, 98808 factory: HammerGesturesPlugin.ɵfac 98809}); 98810 98811(function () { 98812 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](HammerGesturesPlugin, [{ 98813 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable 98814 }], function () { 98815 return [{ 98816 type: undefined, 98817 decorators: [{ 98818 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 98819 args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT] 98820 }] 98821 }, {
98822 type: HammerGestureConfig, 98823 decorators: [{ 98824 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 98825 args: [HAMMER_GESTURE_CONFIG] 98826 }] 98827 }, { 98828 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵConsole"] 98829 }, { 98830 type: undefined, 98831 decorators: [{ 98832 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional 98833 }, { 98834 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 98835 args: [HAMMER_LOADER] 98836 }] 98837 }]; 98838 }, null); 98839})(); 98840/** 98841 * Adds support for HammerJS. 98842 * 98843 * Import this module at the root of your application so that Angular can work with 98844 * HammerJS to detect gesture events. 98845 * 98846 * Note that applications still need to include the HammerJS script itself. This module 98847 * simply sets up the coordination layer between HammerJS and Angular's EventManager. 98848 * 98849 * @publicApi 98850 */ 98851 98852 98853class HammerModule {} 98854 98855HammerModule.ɵfac = function HammerModule_Factory(t) { 98856 return new (t || HammerModule)(); 98857}; 98858 98859HammerModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineNgModule"]({ 98860 type: HammerModule 98861}); 98862HammerModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjector"]({ 98863 providers: [{ 98864 provide: EVENT_MANAGER_PLUGINS, 98865 useClass: HammerGesturesPlugin, 98866 multi: true, 98867 deps: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT, HAMMER_GESTURE_CONFIG, _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵConsole"], [new _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional(), HAMMER_LOADER]] 98868 }, { 98869 provide: HAMMER_GESTURE_CONFIG, 98870 useClass: HammerGestureConfig, 98871 deps: [] 98872 }] 98873}); 98874 98875(function () { 98876 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](HammerModule, [{ 98877 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgModule, 98878 args: [{ 98879 providers: [{ 98880 provide: EVENT_MANAGER_PLUGINS, 98881 useClass: HammerGesturesPlugin, 98882 multi: true, 98883 deps: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT, HAMMER_GESTURE_CONFIG, _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵConsole"], [new _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional(), HAMMER_LOADER]] 98884 }, { 98885 provide: HAMMER_GESTURE_CONFIG, 98886 useClass: HammerGestureConfig, 98887 deps: [] 98888 }] 98889 }] 98890 }], null, null); 98891})(); 98892/** 98893 * @license 98894 * Copyright Google LLC All Rights Reserved. 98895 * 98896 * Use of this source code is governed by an MIT-style license that can be 98897 * found in the LICENSE file at https://angular.io/license 98898 */ 98899 98900/** 98901 * DomSanitizer helps preventing Cross Site Scripting Security bugs (XSS) by sanitizing 98902 * values to be safe to use in the different DOM contexts. 98903 * 98904 * For example, when binding a URL in an `<a [href]="someValue">` hyperlink, `someValue` will be 98905 * sanitized so that an attacker cannot inject e.g. a `javascript:` URL that would execute code on 98906 * the website. 98907 * 98908 * In specific situations, it might be necessary to disable sanitization, for example if the 98909 * application genuinely needs to produce a `javascript:` style link with a dynamic value in it. 98910 * Users can bypass security by constructing a value with one of the `bypassSecurityTrust...` 98911 * methods, and then binding to that value from the template. 98912 * 98913 * These situations should be very rare, and extraordinary care must be taken to avoid creating a 98914 * Cross Site Scripting (XSS) security bug! 98915 * 98916 * When using `bypassSecurityTrust...`, make sure to call the method as early as possible and as 98917 * close as possible to the source of the value, to make it easy to verify no security bug is 98918 * created by its use. 98919 * 98920 * It is not required (and not recommended) to bypass security if the value is safe, e.g. a URL that 98921 * does not start with a suspicious protocol, or an HTML snippet that does not contain dangerous 98922 * code. The sanitizer leaves safe values intact. 98923 * 98924 * @security Calling any of the `bypassSecurityTrust...` APIs disables Angular's built-in 98925 * sanitization for the value passed in. Carefully check and audit all values and code paths going 98926 * into this call. Make sure any user data is appropriately escaped for this security context. 98927 * For more detail, see the [Security Guide](https://g.co/ng/security). 98928 * 98929 * @publicApi 98930 */ 98931 98932 98933class DomSanitizer {} 98934 98935DomSanitizer.ɵfac = function DomSanitizer_Factory(t) { 98936 return new (t || DomSanitizer)(); 98937}; 98938 98939DomSanitizer.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 98940 token: DomSanitizer, 98941 factory: function DomSanitizer_Factory(t) { 98942 let r = null; 98943 98944 if (t) { 98945 r = new (t || DomSanitizer)(); 98946 } else { 98947 r = _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](DomSanitizerImpl); 98948 } 98949 98950 return r; 98951 }, 98952 providedIn: 'root' 98953}); 98954 98955(function () { 98956 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](DomSanitizer, [{ 98957 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable, 98958 args: [{ 98959 providedIn: 'root', 98960 useExisting: (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.forwardRef)(() => DomSanitizerImpl) 98961 }] 98962 }], null, null); 98963})(); 98964 98965function domSanitizerImplFactory(injector) { 98966 return new DomSanitizerImpl(injector.get(_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT)); 98967} 98968 98969class DomSanitizerImpl extends DomSanitizer { 98970 constructor(_doc) { 98971 super(); 98972 this._doc = _doc; 98973 } 98974 98975 sanitize(ctx, value) { 98976 if (value == null) return null; 98977 98978 switch (ctx) { 98979 case _angular_core__WEBPACK_IMPORTED_MODULE_1__.SecurityContext.NONE: 98980 return value; 98981 98982 case _angular_core__WEBPACK_IMPORTED_MODULE_1__.SecurityContext.HTML: 98983 if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵallowSanitizationBypassAndThrow"])(value, "HTML" 98984 /* BypassType.Html */ 98985 )) { 98986 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵunwrapSafeValue"])(value); 98987 } 98988 98989 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵ_sanitizeHtml"])(this._doc, String(value)).toString(); 98990 98991 case _angular_core__WEBPACK_IMPORTED_MODULE_1__.SecurityContext.STYLE: 98992 if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵallowSanitizationBypassAndThrow"])(value, "Style" 98993 /* BypassType.Style */ 98994 )) { 98995 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵunwrapSafeValue"])(value); 98996 } 98997 98998 return value; 98999 99000 case _angular_core__WEBPACK_IMPORTED_MODULE_1__.SecurityContext.SCRIPT: 99001 if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵallowSanitizationBypassAndThrow"])(value, "Script" 99002 /* BypassType.Script */ 99003 )) { 99004 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵunwrapSafeValue"])(value); 99005 } 99006 99007 throw new Error('unsafe value used in a script context'); 99008 99009 case _angular_core__WEBPACK_IMPORTED_MODULE_1__.SecurityContext.URL: 99010 if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵallowSanitizationBypassAndThrow"])(value, "URL" 99011 /* BypassType.Url */ 99012 )) { 99013 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵunwrapSafeValue"])(value); 99014 } 99015 99016 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵ_sanitizeUrl"])(String(value)); 99017 99018 case _angular_core__WEBPACK_IMPORTED_MODULE_1__.SecurityContext.RESOURCE_URL: 99019 if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵallowSanitizationBypassAndThrow"])(value, "ResourceURL" 99020 /* BypassType.ResourceUrl */ 99021 )) { 99022 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵunwrapSafeValue"])(value); 99023 } 99024 99025 throw new Error('unsafe value used in a resource URL context (see https://g.co/ng/security#xss)'); 99026 99027 default: 99028 throw new Error(`Unexpected SecurityContext ${ctx} (see https://g.co/ng/security#xss)`); 99029 } 99030 } 99031 99032 bypassSecurityTrustHtml(value) { 99033 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵbypassSanitizationTrustHtml"])(value); 99034 } 99035 99036 bypassSecurityTrustStyle(value) { 99037 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵbypassSanitizationTrustStyle"])(value); 99038 } 99039 99040 bypassSecurityTrustScript(value) { 99041 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵbypassSanitizationTrustScript"])(value); 99042 } 99043 99044 bypassSecurityTrustUrl(value) { 99045 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵbypassSanitizationTrustUrl"])(value); 99046 } 99047 99048 bypassSecurityTrustResourceUrl(value) { 99049 return (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵbypassSanitizationTrustResourceUrl"])(value); 99050 } 99051 99052} 99053 99054DomSanitizerImpl.ɵfac = function DomSanitizerImpl_Factory(t) { 99055 return new (t || DomSanitizerImpl)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT)); 99056}; 99057 99058DomSanitizerImpl.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 99059 token: DomSanitizerImpl, 99060 factory: function DomSanitizerImpl_Factory(t) { 99061 let r = null; 99062 99063 if (t) { 99064 r = new t(); 99065 } else { 99066 r = domSanitizerImplFactory(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__.Injector)); 99067 } 99068 99069 return r; 99070 }, 99071 providedIn: 'root' 99072}); 99073 99074(function () { 99075 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](DomSanitizerImpl, [{ 99076 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable, 99077 args: [{ 99078 providedIn: 'root', 99079 useFactory: domSanitizerImplFactory, 99080 deps: [_angular_core__WEBPACK_IMPORTED_MODULE_1__.Injector] 99081 }] 99082 }], function () { 99083 return [{ 99084 type: undefined, 99085 decorators: [{ 99086 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 99087 args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__.DOCUMENT] 99088 }] 99089 }]; 99090 }, null); 99091})(); 99092/** 99093 * @license 99094 * Copyright Google LLC All Rights Reserved. 99095 * 99096 * Use of this source code is governed by an MIT-style license that can be 99097 * found in the LICENSE file at https://angular.io/license 99098 */ 99099 99100/** 99101 * @license 99102 * Copyright Google LLC All Rights Reserved. 99103 * 99104 * Use of this source code is governed by an MIT-style license that can be 99105 * found in the LICENSE file at https://angular.io/license 99106 */ 99107 99108/** 99109 * @publicApi 99110 */ 99111 99112 99113const VERSION = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.Version('14.2.10'); 99114/** 99115 * @license 99116 * Copyright Google LLC All Rights Reserved. 99117 * 99118 * Use of this source code is governed by an MIT-style license that can be 99119 * found in the LICENSE file at https://angular.io/license 99120 */ 99121 99122/** 99123 * @license 99124 * Copyright Google LLC All Rights Reserved. 99125 * 99126 * Use of this source code is governed by an MIT-style license that can be 99127 * found in the LICENSE file at https://angular.io/license 99128 */ 99129// This file only reexports content of the `src` folder. Keep it that way. 99130 99131/** 99132 * @license 99133 * Copyright Google LLC All Rights Reserved. 99134 * 99135 * Use of this source code is governed by an MIT-style license that can be 99136 * found in the LICENSE file at https://angular.io/license 99137 */ 99138 99139/** 99140 * Generated bundle index. Do not edit. 99141 */ 99142 99143 99144 99145/***/ }), 99146 99147/***/ 124: 99148/*!**********************************************************!*\ 99149 !*** ./node_modules/@angular/router/fesm2020/router.mjs ***! 99150 \**********************************************************/ 99151/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 99152 99153__webpack_require__.r(__webpack_exports__); 99154/* harmony export */ __webpack_require__.d(__webpack_exports__, { 99155/* harmony export */ "ActivatedRoute": () => (/* binding */ ActivatedRoute), 99156/* harmony export */ "ActivatedRouteSnapshot": () => (/* binding */ ActivatedRouteSnapshot), 99157/* harmony export */ "ActivationEnd": () => (/* binding */ ActivationEnd), 99158/* harmony export */ "ActivationStart": () => (/* binding */ ActivationStart), 99159/* harmony export */ "BaseRouteReuseStrategy": () => (/* binding */ BaseRouteReuseStrategy), 99160/* harmony export */ "ChildActivationEnd": () => (/* binding */ ChildActivationEnd), 99161/* harmony export */ "ChildActivationStart": () => (/* binding */ ChildActivationStart), 99162/* harmony export */ "ChildrenOutletContexts": () => (/* binding */ ChildrenOutletContexts), 99163/* harmony export */ "DefaultTitleStrategy": () => (/* binding */ DefaultTitleStrategy), 99164/* harmony export */ "DefaultUrlSerializer": () => (/* binding */ DefaultUrlSerializer), 99165/* harmony export */ "GuardsCheckEnd": () => (/* binding */ GuardsCheckEnd), 99166/* harmony export */ "GuardsCheckStart": () => (/* binding */ GuardsCheckStart), 99167/* harmony export */ "NavigationCancel": () => (/* binding */ NavigationCancel), 99168/* harmony export */ "NavigationEnd": () => (/* binding */ NavigationEnd), 99169/* harmony export */ "NavigationError": () => (/* binding */ NavigationError), 99170/* harmony export */ "NavigationStart": () => (/* binding */ NavigationStart), 99171/* harmony export */ "NoPreloading": () => (/* binding */ NoPreloading), 99172/* harmony export */ "OutletContext": () => (/* binding */ OutletContext), 99173/* harmony export */ "PRIMARY_OUTLET": () => (/* binding */ PRIMARY_OUTLET), 99174/* harmony export */ "PreloadAllModules": () => (/* binding */ PreloadAllModules), 99175/* harmony export */ "PreloadingStrategy": () => (/* binding */ PreloadingStrategy), 99176/* harmony export */ "ROUTER_CONFIGURATION": () => (/* binding */ ROUTER_CONFIGURATION), 99177/* harmony export */ "ROUTER_INITIALIZER": () => (/* binding */ ROUTER_INITIALIZER), 99178/* harmony export */ "ROUTES": () => (/* binding */ ROUTES), 99179/* harmony export */ "ResolveEnd": () => (/* binding */ ResolveEnd), 99180/* harmony export */ "ResolveStart": () => (/* binding */ ResolveStart), 99181/* harmony export */ "RouteConfigLoadEnd": () => (/* binding */ RouteConfigLoadEnd), 99182/* harmony export */ "RouteConfigLoadStart": () => (/* binding */ RouteConfigLoadStart), 99183/* harmony export */ "RouteReuseStrategy": () => (/* binding */ RouteReuseStrategy), 99184/* harmony export */ "Router": () => (/* binding */ Router), 99185/* harmony export */ "RouterEvent": () => (/* binding */ RouterEvent), 99186/* harmony export */ "RouterLink": () => (/* binding */ RouterLink), 99187/* harmony export */ "RouterLinkActive": () => (/* binding */ RouterLinkActive), 99188/* harmony export */ "RouterLinkWithHref": () => (/* binding */ RouterLinkWithHref), 99189/* harmony export */ "RouterModule": () => (/* binding */ RouterModule), 99190/* harmony export */ "RouterOutlet": () => (/* binding */ RouterOutlet), 99191/* harmony export */ "RouterPreloader": () => (/* binding */ RouterPreloader), 99192/* harmony export */ "RouterState": () => (/* binding */ RouterState), 99193/* harmony export */ "RouterStateSnapshot": () => (/* binding */ RouterStateSnapshot), 99194/* harmony export */ "RoutesRecognized": () => (/* binding */ RoutesRecognized), 99195/* harmony export */ "Scroll": () => (/* binding */ Scroll), 99196/* harmony export */ "TitleStrategy": () => (/* binding */ TitleStrategy), 99197/* harmony export */ "UrlHandlingStrategy": () => (/* binding */ UrlHandlingStrategy), 99198/* harmony export */ "UrlSegment": () => (/* binding */ UrlSegment), 99199/* harmony export */ "UrlSegmentGroup": () => (/* binding */ UrlSegmentGroup), 99200/* harmony export */ "UrlSerializer": () => (/* binding */ UrlSerializer), 99201/* harmony export */ "UrlTree": () => (/* binding */ UrlTree), 99202/* harmony export */ "VERSION": () => (/* binding */ VERSION), 99203/* harmony export */ "convertToParamMap": () => (/* binding */ convertToParamMap), 99204/* harmony export */ "createUrlTreeFromSnapshot": () => (/* binding */ createUrlTreeFromSnapshot), 99205/* harmony export */ "defaultUrlMatcher": () => (/* binding */ defaultUrlMatcher), 99206/* harmony export */ "provideRouter": () => (/* binding */ provideRouter), 99207/* harmony export */ "provideRoutes": () => (/* binding */ provideRoutes), 99208/* harmony export */ "withDebugTracing": () => (/* binding */ withDebugTracing), 99209/* harmony export */ "withDisabledInitialNavigation": () => (/* binding */ withDisabledInitialNavigation), 99210/* harmony export */ "withEnabledBlockingInitialNavigation": () => (/* binding */ withEnabledBlockingInitialNavigation), 99211/* harmony export */ "withInMemoryScrolling": () => (/* binding */ withInMemoryScrolling), 99212/* harmony export */ "withPreloading": () => (/* binding */ withPreloading), 99213/* harmony export */ "withRouterConfig": () => (/* binding */ withRouterConfig), 99214/* harmony exp
99214ort */ "ɵEmptyOutletComponent": () => (/* binding */ ɵEmptyOutletComponent), 99215/* harmony export */ "ɵROUTER_PROVIDERS": () => (/* binding */ ROUTER_PROVIDERS), 99216/* harmony export */ "ɵassignExtraOptionsToRouter": () => (/* binding */ assignExtraOptionsToRouter), 99217/* harmony export */ "ɵflatten": () => (/* binding */ flatten), 99218/* harmony export */ "ɵwithPreloading": () => (/* binding */ withPreloading) 99219/* harmony export */ }); 99220/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 2560); 99221/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs */ 4383); 99222/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 4139); 99223/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 4505); 99224/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs */ 213); 99225/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs */ 9193); 99226/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! rxjs */ 5828); 99227/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! rxjs */ 2160); 99228/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! rxjs */ 6800); 99229/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! rxjs */ 6587); 99230/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! rxjs */ 2378); 99231/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! rxjs */ 6439); 99232/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! rxjs */ 4483); 99233/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! rxjs */ 2218); 99234/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! @angular/common */ 4666); 99235/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs/operators */ 6942); 99236/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs/operators */ 9095); 99237/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs/operators */ 3910); 99238/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! rxjs/operators */ 5722); 99239/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! rxjs/operators */ 9151); 99240/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! rxjs/operators */ 522); 99241/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! rxjs/operators */ 5670); 99242/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! rxjs/operators */ 1133); 99243/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! rxjs/operators */ 8759); 99244/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! rxjs/operators */ 7418); 99245/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! rxjs/operators */ 2647); 99246/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! rxjs/operators */ 5690); 99247/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! rxjs/operators */ 5050); 99248/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! rxjs/operators */ 9701); 99249/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! rxjs/operators */ 7760); 99250/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! rxjs/operators */ 9361); 99251/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! rxjs/operators */ 4661); 99252/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! rxjs/operators */ 8331); 99253/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! rxjs/operators */ 6675); 99254/* harmony import */ var _angular_platform_browser__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! @angular/platform-browser */ 4497); 99255/** 99256 * @license Angular v14.2.10 99257 * (c) 2010-2022 Google LLC. https://angular.io/ 99258 * License: MIT 99259 */ 99260 99261 99262 99263 99264 99265 99266 99267/** 99268 * @license 99269 * Copyright Google LLC All Rights Reserved. 99270 * 99271 * Use of this source code is governed by an MIT-style license that can be 99272 * found in the LICENSE file at https://angular.io/license 99273 */ 99274 99275/** 99276 * The primary routing outlet. 99277 * 99278 * @publicApi 99279 */ 99280 99281const PRIMARY_OUTLET = 'primary'; 99282/** 99283 * A private symbol used to store the value of `Route.title` inside the `Route.data` if it is a 99284 * static string or `Route.resolve` if anything else. This allows us to reuse the existing route 99285 * data/resolvers to support the title feature without new instrumentation in the `Router` pipeline. 99286 */ 99287 99288const RouteTitleKey = Symbol('RouteTitle'); 99289 99290class ParamsAsMap { 99291 constructor(params) { 99292 this.params = params || {}; 99293 } 99294 99295 has(name) { 99296 return Object.prototype.hasOwnProperty.call(this.params, name); 99297 } 99298 99299 get(name) { 99300 if (this.has(name)) { 99301 const v = this.params[name]; 99302 return Array.isArray(v) ? v[0] : v; 99303 } 99304 99305 return null; 99306 } 99307 99308 getAll(name) { 99309 if (this.has(name)) { 99310 const v = this.params[name]; 99311 return Array.isArray(v) ? v : [v]; 99312 } 99313 99314 return []; 99315 } 99316 99317 get keys() { 99318 return Object.keys(this.params); 99319 } 99320 99321} 99322/**
99323 * Converts a `Params` instance to a `ParamMap`. 99324 * @param params The instance to convert. 99325 * @returns The new map instance. 99326 * 99327 * @publicApi 99328 */ 99329 99330 99331function convertToParamMap(params) { 99332 return new ParamsAsMap(params); 99333} 99334/** 99335 * Matches the route configuration (`route`) against the actual URL (`segments`). 99336 * 99337 * When no matcher is defined on a `Route`, this is the matcher used by the Router by default. 99338 * 99339 * @param segments The remaining unmatched segments in the current navigation 99340 * @param segmentGroup The current segment group being matched 99341 * @param route The `Route` to match against. 99342 * 99343 * @see UrlMatchResult 99344 * @see Route 99345 * 99346 * @returns The resulting match information or `null` if the `route` should not match. 99347 * @publicApi 99348 */ 99349 99350 99351function defaultUrlMatcher(segments, segmentGroup, route) { 99352 const parts = route.path.split('/'); 99353 99354 if (parts.length > segments.length) { 99355 // The actual URL is shorter than the config, no match 99356 return null; 99357 } 99358 99359 if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || parts.length < segments.length)) { 99360 // The config is longer than the actual URL but we are looking for a full match, return null 99361 return null; 99362 } 99363 99364 const posParams = {}; // Check each config part against the actual URL 99365 99366 for (let index = 0; index < parts.length; index++) { 99367 const part = parts[index]; 99368 const segment = segments[index]; 99369 const isParameter = part.startsWith(':'); 99370 99371 if (isParameter) { 99372 posParams[part.substring(1)] = segment; 99373 } else if (part !== segment.path) { 99374 // The actual URL part does not match the config, no match 99375 return null; 99376 } 99377 } 99378 99379 return { 99380 consumed: segments.slice(0, parts.length), 99381 posParams 99382 }; 99383} 99384/** 99385 * @license 99386 * Copyright Google LLC All Rights Reserved. 99387 * 99388 * Use of this source code is governed by an MIT-style license that can be 99389 * found in the LICENSE file at https://angular.io/license 99390 */ 99391 99392 99393function shallowEqualArrays(a, b) { 99394 if (a.length !== b.length) return false; 99395 99396 for (let i = 0; i < a.length; ++i) { 99397 if (!shallowEqual(a[i], b[i])) return false; 99398 } 99399 99400 return true; 99401} 99402 99403function shallowEqual(a, b) { 99404 // While `undefined` should never be possible, it would sometimes be the case in IE 11 99405 // and pre-chromium Edge. The check below accounts for this edge case. 99406 const k1 = a ? Object.keys(a) : undefined; 99407 const k2 = b ? Object.keys(b) : undefined; 99408 99409 if (!k1 || !k2 || k1.length != k2.length) { 99410 return false; 99411 } 99412 99413 let key; 99414 99415 for (let i = 0; i < k1.length; i++) { 99416 key = k1[i]; 99417 99418 if (!equalArraysOrString(a[key], b[key])) { 99419 return false; 99420 } 99421 } 99422 99423 return true; 99424} 99425/**
99426 * Test equality for arrays of strings or a string. 99427 */ 99428 99429 99430function equalArraysOrString(a, b) { 99431 if (Array.isArray(a) && Array.isArray(b)) { 99432 if (a.length !== b.length) return false; 99433 const aSorted = [...a].sort(); 99434 const bSorted = [...b].sort(); 99435 return aSorted.every((val, index) => bSorted[index] === val); 99436 } else { 99437 return a === b; 99438 } 99439} 99440/** 99441 * Flattens single-level nested arrays. 99442 */ 99443 99444 99445function flatten(arr) { 99446 return Array.prototype.concat.apply([], arr); 99447} 99448/** 99449 * Return the last element of an array. 99450 */ 99451 99452 99453function last(a) { 99454 return a.length > 0 ? a[a.length - 1] : null; 99455} 99456/** 99457 * Verifys all booleans in an array are `true`. 99458 */ 99459 99460 99461function and(bools) { 99462 return !bools.some(v => !v); 99463} 99464 99465function forEach(map, callback) { 99466 for (const prop in map) { 99467 if (map.hasOwnProperty(prop)) { 99468 callback(map[prop], prop); 99469 } 99470 } 99471} 99472 99473function wrapIntoObservable(value) { 99474 if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisObservable"])(value)) { 99475 return value; 99476 } 99477 99478 if ((0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisPromise"])(value)) { 99479 // Use `Promise.resolve()` to wrap promise-like instances. 99480 // Required ie when a Resolver returns a AngularJS `$q` promise to correctly trigger the 99481 // change detection. 99482 return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(Promise.resolve(value)); 99483 } 99484 99485 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(value); 99486} 99487/** 99488 * @license 99489 * Copyright Google LLC All Rights Reserved. 99490 * 99491 * Use of this source code is governed by an MIT-style license that can be 99492 * found in the LICENSE file at https://angular.io/license 99493 */ 99494 99495 99496const NG_DEV_MODE$9 = typeof ngDevMode === 'undefined' || ngDevMode; 99497 99498function createEmptyUrlTree() { 99499 return new UrlTree(new UrlSegmentGroup([], {}), {}, null); 99500} 99501 99502const pathCompareMap = { 99503 'exact': equalSegmentGroups, 99504 'subset': containsSegmentGroup 99505}; 99506const paramCompareMap = { 99507 'exact': equalParams, 99508 'subset': containsParams, 99509 'ignored': () => true 99510}; 99511 99512function containsTree(container, containee, options) { 99513 return pathCompareMap[options.paths](container.root, containee.root, options.matrixParams) && paramCompareMap[options.queryParams](container.queryParams, containee.queryParams) && !(options.fragment === 'exact' && container.fragment !== containee.fragment); 99514} 99515 99516function equalParams(container, containee) { 99517 // TODO: This does not handle array params correctly. 99518 return shallowEqual(container, containee); 99519} 99520 99521function equalSegmentGroups(container, containee, matrixParams) { 99522 if (!equalPath(container.segments, containee.segments)) return false; 99523 99524 if (!matrixParamsMatch(container.segments, containee.segments, matrixParams)) { 99525 return false; 99526 } 99527 99528 if (container.numberOfChildren !== containee.numberOfChildren) return false; 99529 99530 for (const c in containee.children) { 99531 if (!container.children[c]) return false; 99532 if (!equalSegmentGroups(container.children[c], containee.children[c], matrixParams)) return false; 99533 } 99534 99535 return true; 99536} 99537 99538function containsParams(container, containee) { 99539 return Object.keys(containee).length <= Object.keys(container).length && Object.keys(containee).every(key => equalArraysOrString(container[key], containee[key])); 99540} 99541 99542function containsSegmentGroup(container, containee, matrixParams) { 99543 return containsSegmentGroupHelper(container, containee, containee.segments, matrixParams); 99544} 99545 99546function containsSegmentGroupHelper(container, containee, containeePaths, matrixParams) { 99547 if (container.segments.length > containeePaths.length) { 99548 const current = container.segments.slice(0, containeePaths.length); 99549 if (!equalPath(current, containeePaths)) return false; 99550 if (containee.hasChildren()) return false; 99551 if (!matrixParamsMatch(current, containeePaths, matrixParams)) return false; 99552 return true; 99553 } else if (container.segments.length === containeePaths.length) { 99554 if (!equalPath(container.segments, containeePaths)) return false; 99555 if (!matrixParamsMatch(container.segments, containeePaths, matrixParams)) return false; 99556 99557 for (const c in containee.children) { 99558 if (!container.children[c]) return false;
99559 99560 if (!containsSegmentGroup(container.children[c], containee.children[c], matrixParams)) { 99561 return false; 99562 } 99563 } 99564 99565 return true; 99566 } else { 99567 const current = containeePaths.slice(0, container.segments.length); 99568 const next = containeePaths.slice(container.segments.length); 99569 if (!equalPath(container.segments, current)) return false; 99570 if (!matrixParamsMatch(container.segments, current, matrixParams)) return false; 99571 if (!container.children[PRIMARY_OUTLET]) return false; 99572 return containsSegmentGroupHelper(container.children[PRIMARY_OUTLET], containee, next, matrixParams); 99573 } 99574} 99575 99576function matrixParamsMatch(containerPaths, containeePaths, options) { 99577 return containeePaths.every((containeeSegment, i) => { 99578 return paramCompareMap[options](containerPaths[i].parameters, containeeSegment.parameters); 99579 }); 99580} 99581/** 99582 * @description 99583 * 99584 * Represents the parsed URL. 99585 * 99586 * Since a router state is a tree, and the URL is nothing but a serialized state, the URL is a 99587 * serialized tree. 99588 * UrlTree is a data structure that provides a lot of affordances in dealing with URLs 99589 * 99590 * @usageNotes 99591 * ### Example 99592 * 99593 * ``` 99594 * @Component({templateUrl:'template.html'}) 99595 * class MyComponent { 99596 * constructor(router: Router) { 99597 * const tree: UrlTree = 99598 * router.parseUrl('/team/33/(user/victor//support:help)?debug=true#fragment'); 99599 * const f = tree.fragment; // return 'fragment' 99600 * const q = tree.queryParams; // returns {debug: 'true'} 99601 * const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET]; 99602 * const s: UrlSegment[] = g.segments; // returns 2 segments 'team' and '33' 99603 * g.children[PRIMARY_OUTLET].segments; // returns 2 segments 'user' and 'victor' 99604 * g.children['support'].segments; // return 1 segment 'help' 99605 * } 99606 * } 99607 * ``` 99608 * 99609 * @publicApi 99610 */ 99611 99612 99613class UrlTree { 99614 /** @internal */ 99615 constructor( 99616 /** The root segment group of the URL tree */ 99617 root, 99618 /** The query params of the URL */ 99619 queryParams, 99620 /** The fragment of the URL */ 99621 fragment) { 99622 this.root = root; 99623 this.queryParams = queryParams; 99624 this.fragment = fragment; 99625 } 99626 99627 get queryParamMap() { 99628 if (!this._queryParamMap) { 99629 this._queryParamMap = convertToParamMap(this.queryParams); 99630 } 99631 99632 return this._queryParamMap; 99633 } 99634 /** @docsNotRequired */ 99635 99636 99637 toString() { 99638 return DEFAULT_SERIALIZER.serialize(this); 99639 } 99640 99641} 99642/** 99643 * @description 99644 * 99645 * Represents the parsed URL segment group. 99646 * 99647 * See `UrlTree` for more information. 99648 * 99649 * @publicApi 99650 */ 99651 99652 99653class UrlSegmentGroup { 99654 constructor( 99655 /** The URL segments of this group. See `UrlSegment` for more information */ 99656 segments, 99657 /** The list of children of this group */ 99658 children) { 99659 this.segments = segments; 99660 this.children = children; 99661 /** The parent node in the url tree */ 99662 99663 this.parent = null; 99664 forEach(children, (v, k) => v.parent = this); 99665 } 99666 /** Whether the segment has child segments */ 99667 99668 99669 hasChildren() { 99670 return this.numberOfChildren > 0; 99671 } 99672 /** Number of child segments */ 99673 99674 99675 get numberOfChildren() { 99676 return Object.keys(this.children).length; 99677 } 99678 /** @docsNotRequired */ 99679 99680 99681 toString() { 99682 return serializePaths(this); 99683 } 99684 99685} 99686/** 99687 * @description 99688 * 99689 * Represents a single URL segment. 99690 * 99691 * A UrlSegment is a part of a URL between the two slashes. It contains a path and the matrix 99692 * parameters associated with the segment. 99693 * 99694 * @usageNotes 99695 *Â ### Example 99696 * 99697 * ``` 99698 * @Component({templateUrl:'template.html'}) 99699 * class MyComponent { 99700 * constructor(router: Router) { 99701 * const tree: UrlTree = router.parseUrl('/team;id=33'); 99702 * const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET]; 99703 * const s: UrlSegment[] = g.segments; 99704 * s[0].path; // returns 'team' 99705 * s[0].parameters; // returns {id: 33} 99706 * } 99707 * } 99708 * ``` 99709 * 99710 * @publicApi 99711 */ 99712 99713 99714class UrlSegment { 99715 constructor( 99716 /** The path part of a URL segment */ 99717 path, 99718 /** The matrix parameters associated with a segment */ 99719 parameters) { 99720 this.path = path; 99721 this.parameters = parameters; 99722 } 99723 99724 get parameterMap() { 99725 if (!this._parameterMap) { 99726 this._parameterMap = convertToParamMap(this.parameters); 99727 } 99728 99729 return this._parameterMap; 99730 } 99731 /** @docsNotRequired */ 99732 99733 99734 toString() { 99735 return serializePath(this); 99736 } 99737 99738} 99739 99740function equalSegments(as, bs) { 99741 return equalPath(as, bs) && as.every((a, i) => shallowEqual(a.parameters, bs[i].parameters)); 99742} 99743 99744function equalPath(as, bs) { 99745 if (as.length !== bs.length) return false;
99746 return as.every((a, i) => a.path === bs[i].path); 99747} 99748 99749function mapChildrenIntoArray(segment, fn) { 99750 let res = []; 99751 forEach(segment.children, (child, childOutlet) => { 99752 if (childOutlet === PRIMARY_OUTLET) { 99753 res = res.concat(fn(child, childOutlet)); 99754 } 99755 }); 99756 forEach(segment.children, (child, childOutlet) => { 99757 if (childOutlet !== PRIMARY_OUTLET) { 99758 res = res.concat(fn(child, childOutlet)); 99759 } 99760 }); 99761 return res; 99762} 99763/** 99764 * @description 99765 * 99766 * Serializes and deserializes a URL string into a URL tree. 99767 * 99768 * The url serialization strategy is customizable. You can 99769 * make all URLs case insensitive by providing a custom UrlSerializer. 99770 * 99771 * See `DefaultUrlSerializer` for an example of a URL serializer. 99772 * 99773 * @publicApi 99774 */ 99775 99776 99777class UrlSerializer {} 99778 99779UrlSerializer.ɵfac = function UrlSerializer_Factory(t) { 99780 return new (t || UrlSerializer)(); 99781}; 99782 99783UrlSerializer.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 99784 token: UrlSerializer, 99785 factory: function () { 99786 return (() => new DefaultUrlSerializer())(); 99787 }, 99788 providedIn: 'root' 99789}); 99790 99791(function () { 99792 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](UrlSerializer, [{ 99793 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 99794 args: [{ 99795 providedIn: 'root', 99796 useFactory: () => new DefaultUrlSerializer() 99797 }] 99798 }], null, null); 99799})(); 99800/** 99801 * @description 99802 * 99803 * A default implementation of the `UrlSerializer`. 99804 * 99805 * Example URLs: 99806 * 99807 * ``` 99808 * /inbox/33(popup:compose) 99809 * /inbox/33;open=true/messages/44 99810 * ``` 99811 * 99812 * DefaultUrlSerializer uses parentheses to serialize secondary segments (e.g., popup:compose), the 99813 * colon syntax to specify the outlet, and the ';parameter=value' syntax (e.g., open=true) to 99814 * specify route specific parameters. 99815 * 99816 * @publicApi 99817 */ 99818 99819 99820class DefaultUrlSerializer { 99821 /** Parses a url into a `UrlTree` */ 99822 parse(url) { 99823 const p = new UrlParser(url); 99824 return new UrlTree(p.parseRootSegment(), p.parseQueryParams(), p.parseFragment()); 99825 } 99826 /** Converts a `UrlTree` into a url */ 99827 99828 99829 serialize(tree) { 99830 const segment = `/${serializeSegment(tree.root, true)}`; 99831 const query = serializeQueryParams(tree.queryParams); 99832 const fragment = typeof tree.fragment === `string` ? `#${encodeUriFragment(tree.fragment)}` : ''; 99833 return `${segment}${query}${fragment}`; 99834 } 99835 99836} 99837 99838const DEFAULT_SERIALIZER = new DefaultUrlSerializer(); 99839 99840function serializePaths(segment) { 99841 return segment.segments.map(p => serializePath(p)).join('/'); 99842} 99843 99844function serializeSegment(segment, root) { 99845 if (!segment.hasChildren()) { 99846 return serializePaths(segment); 99847 } 99848 99849 if (root) { 99850 const primary = segment.children[PRIMARY_OUTLET] ? serializeSegment(segment.children[PRIMARY_OUTLET], false) : ''; 99851 const children = []; 99852 forEach(segment.children, (v, k) => { 99853 if (k !== PRIMARY_OUTLET) { 99854 children.push(`${k}:${serializeSegment(v, false)}`); 99855 } 99856 }); 99857 return children.length > 0 ? `${primary}(${children.join('//')})` : primary; 99858 } else { 99859 const children = mapChildrenIntoArray(segment, (v, k) => { 99860 if (k === PRIMARY_OUTLET) { 99861 return [serializeSegment(segment.children[PRIMARY_OUTLET], false)]; 99862 } 99863 99864 return [`${k}:${serializeSegment(v, false)}`]; 99865 }); // use no parenthesis if the only child is a primary outlet route 99866 99867 if (Object.keys(segment.children).length === 1 && segment.children[PRIMARY_OUTLET] != null) { 99868 return `${serializePaths(segment)}/${children[0]}`; 99869 } 99870 99871 return `${serializePaths(segment)}/(${children.join('//')})`; 99872 } 99873} 99874/** 99875 * Encodes a URI string with the default encoding. This function will only ever be called from 99876 * `encodeUriQuery` or `encodeUriSegment` as it's the base set of encodings to be used. We need 99877 * a custom encoding because encodeURIComponent is too aggressive and encodes stuff that doesn't 99878 * have to be encoded per https://url.spec.whatwg.org. 99879 */ 99880 99881 99882function encodeUriString(s) { 99883 return encodeURIComponent(s).replace(/%40/g, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ','); 99884} 99885/** 99886 * This function should be used to encode both keys and values in a query string key/value. In 99887 * the following URL, you need to call encodeUriQuery on "k" and "v": 99888 * 99889 * http://www.site.org/html;mk=mv?k=v#f 99890 */ 99891 99892 99893function encodeUriQuery(s) { 99894 return encodeUriString(s).replace(/%3B/gi, ';'); 99895} 99896/** 99897 * This function should be used to encode a URL fragment. In the following URL, you need to call
99898 * encodeUriFragment on "f": 99899 * 99900 * http://www.site.org/html;mk=mv?k=v#f 99901 */ 99902 99903 99904function encodeUriFragment(s) { 99905 return encodeURI(s); 99906} 99907/** 99908 * This function should be run on any URI segment as well as the key and value in a key/value 99909 * pair for matrix params. In the following URL, you need to call encodeUriSegment on "html", 99910 * "mk", and "mv": 99911 * 99912 * http://www.site.org/html;mk=mv?k=v#f 99913 */ 99914 99915 99916function encodeUriSegment(s) { 99917 return encodeUriString(s).replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/%26/gi, '&'); 99918} 99919 99920function decode(s) { 99921 return decodeURIComponent(s); 99922} // Query keys/values should have the "+" replaced first, as "+" in a query string is " ". 99923// decodeURIComponent function will not decode "+" as a space. 99924 99925 99926function decodeQuery(s) { 99927 return decode(s.replace(/\+/g, '%20')); 99928} 99929 99930function serializePath(path) { 99931 return `${encodeUriSegment(path.path)}${serializeMatrixParams(path.parameters)}`; 99932} 99933 99934function serializeMatrixParams(params) { 99935 return Object.keys(params).map(key => `;${encodeUriSegment(key)}=${encodeUriSegment(params[key])}`).join(''); 99936} 99937 99938function serializeQueryParams(params) { 99939 const strParams = Object.keys(params).map(name => { 99940 const value = params[name]; 99941 return Array.isArray(value) ? value.map(v => `${encodeUriQuery(name)}=${encodeUriQuery(v)}`).join('&') : `${encodeUriQuery(name)}=${encodeUriQuery(value)}`; 99942 }).filter(s => !!s); 99943 return strParams.length ? `?${strParams.join('&')}` : ''; 99944} 99945 99946const SEGMENT_RE = /^[^\/()?;=#]+/; 99947 99948function matchSegments(str) { 99949 const match = str.match(SEGMENT_RE); 99950 return match ? match[0] : ''; 99951} 99952 99953const QUERY_PARAM_RE = /^[^=?&#]+/; // Return the name of the query param at the start of the string or an empty string 99954 99955function matchQueryParams(str) { 99956 const match = str.match(QUERY_PARAM_RE); 99957 return match ? match[0] : ''; 99958} 99959 99960const QUERY_PARAM_VALUE_RE = /^[^&#]+/; // Return the value of the query param at the start of the string or an empty string 99961 99962function matchUrlQueryParamValue(str) { 99963 const match = str.match(QUERY_PARAM_VALUE_RE); 99964 return match ? match[0] : ''; 99965} 99966 99967class UrlParser { 99968 constructor(url) { 99969 this.url = url; 99970 this.remaining = url; 99971 } 99972 99973 parseRootSegment() { 99974 this.consumeOptional('/'); 99975 99976 if (this.remaining === '' || this.peekStartsWith('?') || this.peekStartsWith('#')) { 99977 return new UrlSegmentGroup([], {}); 99978 } // The root segment group never has segments 99979 99980 99981 return new UrlSegmentGroup([], this.parseChildren()); 99982 } 99983 99984 parseQueryParams() { 99985 const params = {}; 99986 99987 if (this.consumeOptional('?')) { 99988 do { 99989 this.parseQueryParam(params); 99990 } while (this.consumeOptional('&')); 99991 } 99992 99993 return params; 99994 } 99995 99996 parseFragment() { 99997 return this.consumeOptional('#') ? decodeURIComponent(this.remaining) : null; 99998 } 99999 100000 parseChildren() { 100001 if (this.remaining === '') { 100002 return {}; 100003 } 100004 100005 this.consumeOptional('/'); 100006 const segments = []; 100007 100008 if (!this.peekStartsWith('(')) { 100009 segments.push(this.parseSegment()); 100010 } 100011 100012 while (this.peekStartsWith('/') && !this.peekStartsWith('//') && !this.peekStartsWith('/(')) { 100013 this.capture('/'); 100014 segments.push(this.parseSegment()); 100015 } 100016 100017 let children = {}; 100018 100019 if (this.peekStartsWith('/(')) { 100020 this.capture('/'); 100021 children = this.parseParens(true); 100022 } 100023 100024 let res = {}; 100025 100026 if (this.peekStartsWith('(')) { 100027 res = this.parseParens(false); 100028 } 100029 100030 if (segments.length > 0 || Object.keys(children).length > 0) { 100031 res[PRIMARY_OUTLET] = new UrlSegmentGroup(segments, children); 100032 } 100033 100034 return res; 100035 } // parse a segment with its matrix parameters 100036 // ie `name;k1=v1;k2` 100037 100038 100039 parseSegment() { 100040 const path = matchSegments(this.remaining); 100041 100042 if (path === '' && this.peekStartsWith(';')) { 100043 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4009 100044 /* RuntimeErrorCode.EMPTY_PATH_WITH_PARAMS */ 100045 , NG_DEV_MODE$9 && `Empty path url segment cannot have parameters: '${this.remaining}'.`); 100046 } 100047 100048 this.capture(path); 100049 return new UrlSegment(decode(path), this.parseMatrixParams()); 100050 } 100051 100052 parseMatrixParams() { 100053 const params = {}; 100054 100055 while (this.consumeOptional(';')) { 100056 this.parseParam(params); 100057 } 100058 100059 return params; 100060 } 100061 100062 parseParam(params) {
100063 const key = matchSegments(this.remaining); 100064 100065 if (!key) { 100066 return; 100067 } 100068 100069 this.capture(key); 100070 let value = ''; 100071 100072 if (this.consumeOptional('=')) { 100073 const valueMatch = matchSegments(this.remaining); 100074 100075 if (valueMatch) { 100076 value = valueMatch; 100077 this.capture(value); 100078 } 100079 } 100080 100081 params[decode(key)] = decode(value); 100082 } // Parse a single query parameter `name[=value]` 100083 100084 100085 parseQueryParam(params) { 100086 const key = matchQueryParams(this.remaining); 100087 100088 if (!key) { 100089 return; 100090 } 100091 100092 this.capture(key); 100093 let value = ''; 100094 100095 if (this.consumeOptional('=')) { 100096 const valueMatch = matchUrlQueryParamValue(this.remaining); 100097 100098 if (valueMatch) { 100099 value = valueMatch; 100100 this.capture(value); 100101 } 100102 } 100103 100104 const decodedKey = decodeQuery(key); 100105 const decodedVal = decodeQuery(value); 100106 100107 if (params.hasOwnProperty(decodedKey)) { 100108 // Append to existing values 100109 let currentVal = params[decodedKey]; 100110 100111 if (!Array.isArray(currentVal)) { 100112 currentVal = [currentVal]; 100113 params[decodedKey] = currentVal; 100114 } 100115 100116 currentVal.push(decodedVal); 100117 } else { 100118 // Create a new value 100119 params[decodedKey] = decodedVal; 100120 } 100121 } // parse `(a/b//outlet_name:c/d)` 100122 100123 100124 parseParens(allowPrimary) { 100125 const segments = {}; 100126 this.capture('('); 100127 100128 while (!this.consumeOptional(')') && this.remaining.length > 0) { 100129 const path = matchSegments(this.remaining); 100130 const next = this.remaining[path.length]; // if is is not one of these characters, then the segment was unescaped 100131 // or the group was not closed 100132 100133 if (next !== '/' && next !== ')' && next !== ';') { 100134 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4010 100135 /* RuntimeErrorCode.UNPARSABLE_URL */ 100136 , NG_DEV_MODE$9 && `Cannot parse url '${this.url}'`); 100137 } 100138 100139 let outletName = undefined; 100140 100141 if (path.indexOf(':') > -1) { 100142 outletName = path.slice(0, path.indexOf(':')); 100143 this.capture(outletName); 100144 this.capture(':'); 100145 } else if (allowPrimary) { 100146 outletName = PRIMARY_OUTLET; 100147 } 100148 100149 const children = this.parseChildren(); 100150 segments[outletName] = Object.keys(children).length === 1 ? children[PRIMARY_OUTLET] : new UrlSegmentGroup([], children); 100151 this.consumeOptional('//'); 100152 } 100153 100154 return segments; 100155 } 100156 100157 peekStartsWith(str) { 100158 return this.remaining.startsWith(str); 100159 } // Consumes the prefix when it is present and returns whether it has been consumed 100160 100161 100162 consumeOptional(str) { 100163 if (this.peekStartsWith(str)) { 100164 this.remaining = this.remaining.substring(str.length); 100165 return true; 100166 } 100167 100168 return false; 100169 } 100170 100171 capture(str) { 100172 if (!this.consumeOptional(str)) { 100173 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4011 100174 /* RuntimeErrorCode.UNEXPECTED_VALUE_IN_URL */ 100175 , NG_DEV_MODE$9 && `Expected "${str}".`); 100176 } 100177 } 100178 100179} 100180 100181function createRoot(rootCandidate) { 100182 return rootCandidate.segments.length > 0 ? new UrlSegmentGroup([], { 100183 [PRIMARY_OUTLET]: rootCandidate 100184 }) : rootCandidate; 100185} 100186/** 100187 * Recursively merges primary segment children into their parents and also drops empty children 100188 * (those which have no segments and no children themselves). The latter prevents serializing a 100189 * group into something like `/a(aux:)`, where `aux` is an empty child segment. 100190 */ 100191 100192 100193function squashSegmentGroup(segmentGroup) { 100194 const newChildren = {}; 100195 100196 for (const childOutlet of Object.keys(segmentGroup.children)) { 100197 const child = segmentGroup.children[childOutlet]; 100198 const childCandidate = squashSegmentGroup(child); // don't add empty children 100199 100200 if (childCandidate.segments.length > 0 || childCandidate.hasChildren()) { 100201 newChildren[childOutlet] = childCandidate; 100202 } 100203 } 100204 100205 const s = new UrlSegmentGroup(segmentGroup.segments, newChildren); 100206 return mergeTrivialChildren(s); 100207} 100208/** 100209 * When possible, merges the primary outlet child into the parent `UrlSegmentGroup`. 100210 * 100211 * When a segment group has only one child which is a primary outlet, merges that child into the 100212 * parent. That is, the child segment group's segments are merged into the `s` and the child's 100213 * children become the children of `s`. Think of this like a 'squash', merging the child segment 100214 * group into the parent. 100215 */ 100216 100217 100218function mergeTrivialChildren(s) { 100219 if (s.numberOfChildren === 1 && s.children[PRIMARY_OUTLET]) { 100220 const c = s.children[PRIMARY_OUTLET]; 100221 return new UrlSegmentGroup(s.segments.concat(c.segments), c.children); 100222 } 100223 100224 return s; 100225} 100226 100227function isUrlTree(v) { 100228 return v instanceof UrlTree; 100229} 100230/** 100231 * @license 100232 * Copyright Google LLC All Rights Reserved. 100233 * 100234 * Use of this source code is governed by an MIT-style license that can be 100235 * found in the LICENSE file at https://angular.io/license 100236 */ 100237 100238 100239const NG_DEV_MODE$8 = typeof ngDevMode === 'undefined' || ngDevMode; 100240/** 100241 * Creates a `UrlTree` relative to an `ActivatedRouteSnapshot`. 100242 * 100243 * @publicApi 100244 * 100245 * 100246 * @param relativeTo The `ActivatedRouteSnapshot` to apply the commands to 100247 * @param commands An array of URL fragments with which to construct the new URL tree. 100248 * If the path is static, can be the literal URL string. For a dynamic path, pass an array of path 100249 * segments, followed by the parameters for each segment. 100250 * The fragments are applied to the one provided in the `relativeTo` parameter. 100251 * @param queryParams The query parameters for the `UrlTree`. `null` if the `UrlTree` does not have 100252 * any query parameters. 100253 * @param fragment The fragment for the `UrlTree`. `null` if the `UrlTree` does not have a fragment. 100254 * 100255 * @usageNotes 100256 * 100257 * ``` 100258 * // create /team/33/user/11 100259 * createUrlTreeFromSnapshot(snapshot, ['/team', 33, 'user', 11]); 100260 * 100261 * // create /team/33;expand=true/user/11 100262 * createUrlTreeFromSnapshot(snapshot, ['/team', 33, {expand: true}, 'user', 11]); 100263 * 100264 * // you can collapse static segments like this (this works only with the first passed-in value): 100265 * createUrlTreeFromSnapshot(snapshot, ['/team/33/user', userId]); 100266 * 100267 * // If the first segment can contain slashes, and you do not want the router to split it, 100268 * // you can do the following: 100269 * createUrlTreeFromSnapshot(snapshot, [{segmentPath: '/one/two'}]); 100270 * 100271 * // create /team/33/(user/11//right:chat) 100272 * createUrlTreeFromSnapshot(snapshot, ['/team', 33, {outlets: {primary: 'user/11', right: 100273 * 'chat'}}], null, null); 100274 * 100275 * // remove the right secondary node 100276 * createUrlTreeFromSnapshot(snapshot, ['/team', 33, {outlets: {primary: 'user/11', right: null}}]); 100277 * 100278 * // For the examples below, assume the current URL is for the `/team/33/user/11` and the 100279 * `ActivatedRouteSnapshot` points to `user/11`: 100280 * 100281 * // navigate to /team/33/user/11/details 100282 * createUrlTreeFromSnapshot(snapshot, ['details']); 100283 * 100284 * // navigate to /team/33/user/22 100285 * createUrlTreeFromSnapshot(snapshot, ['../22']); 100286 * 100287 * // navigate to /team/44/user/22 100288 * createUrlTreeFromSnapshot(snapshot, ['../../team/44/user/22']); 100289 * ``` 100290 */ 100291 100292function createUrlTreeFromSnapshot(relativeTo, commands, queryParams = null, fragment = null) { 100293 const relativeToUrlSegmentGroup = createSegmentGroupFromRoute(relativeTo); 100294 return createUrlTreeFromSegmentGroup(relativeToUrlSegmentGroup, commands, queryParams, fragment); 100295} 100296 100297function createSegmentGroupFromRoute(route) { 100298 let targetGroup; 100299 100300 function createSegmentGroupFromRouteRecursive(currentRoute) { 100301 const childOutlets = {}; 100302 100303 for (const childSnapshot of currentRoute.children) { 100304 const root = createSegmentGroupFromRouteRecursive(childSnapshot); 100305 childOutlets[childSnapshot.outlet] = root; 100306 } 100307 100308 const segmentGroup = new UrlSegmentGroup(currentRoute.url, childOutlets); 100309 100310 if (currentRoute === route) { 100311 targetGroup = segmentGroup; 100312 } 100313 100314 return segmentGroup; 100315 } 100316 100317 const rootCandidate = createSegmentGroupFromRouteRecursive(route.root); 100318 const rootSegmentGroup = createRoot(rootCandidate); 100319 return targetGroup ?? rootSegmentGroup; 100320} 100321 100322function createUrlTreeFromSegmentGroup(relativeTo, commands, queryParams, fragment) { 100323 let root = relativeTo; 100324 100325 while (root.parent) { 100326 root = root.parent; 100327 } // There are no commands so the `UrlTree` goes to the same path as the one created from the 100328 // `UrlSegmentGroup`. All we need to do is update the `queryParams` and `fragment` without 100329 // applying any other logic. 100330 100331 100332 if (commands.length === 0) { 100333 return tree(root, root, root, queryParams, fragment); 100334 } 100335 100336 const nav = computeNavigation(commands); 100337 100338 if (nav.toRoot()) { 100339 return tree(root, root, new UrlSegmentGroup([], {}), queryParams, fragment); 100340 } 100341 100342 const position = findStartingPositionForTargetGroup(nav, root, relativeTo); 100343 const newSegmentGroup = position.processChildren ? updateSegmentGroupChildren(position.segmentGroup, position.index, nav.commands) : updateSegmentGroup(position.segmentGroup, position.index, nav.commands); 100344 return tree(root, position.segmentGroup, newSegmentGroup, queryParams, fragment); 100345} 100346 100347function createUrlTree(route, urlTree, commands, queryParams, fragment) { 100348 if (commands.length === 0) { 100349 return tree(urlTree.root, urlTree.root, urlTree.root, queryParams, fragment); 100350 } 100351 100352 const nav = computeNavigation(commands); 100353 100354 if (nav.toRoot()) { 100355 return tree(urlTree.root, urlTree.root, new UrlSegmentGroup([], {}), queryParams, fragment); 100356 } 100357 100358 function createTreeUsingPathIndex(lastPathIndex) { 100359 const startingPosition = findStartingPosition(nav, urlTree, route.
100359snapshot?._urlSegment, lastPathIndex); 100360 const segmentGroup = startingPosition.processChildren ? updateSegmentGroupChildren(startingPosition.segmentGroup, startingPosition.index, nav.commands) : updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands); 100361 return tree(urlTree.root, startingPosition.segmentGroup, segmentGroup, queryParams, fragment); 100362 } // Note: The types should disallow `snapshot` from being `undefined` but due to test mocks, this 100363 // may be the case. Since we try to access it at an earlier point before the refactor to add the 100364 // warning for `relativeLinkResolution: 'legacy'`, this may cause failures in tests where it 100365 // didn't before. 100366 100367 100368 const result = createTreeUsingPathIndex(route.snapshot?._lastPathIndex); // Check if application is relying on `relativeLinkResolution: 'legacy'` 100369 100370 if (typeof ngDevMode === 'undefined' || !!ngDevMode) { 100371 const correctedResult = createTreeUsingPathIndex(route.snapshot?._correctedLastPathIndex); 100372 100373 if (correctedResult.toString() !== result.toString()) { 100374 console.warn(`relativeLinkResolution: 'legacy' is deprecated and will be removed in a future version of Angular. The link to ${result.toString()} will change to ${correctedResult.toString()} if the code is not updated before then.`); 100375 } 100376 } 100377 100378 return result; 100379} 100380 100381function isMatrixParams(command) { 100382 return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath; 100383} 100384/** 100385 * Determines if a given command has an `outlets` map. When we encounter a command 100386 * with an outlets k/v map, we need to apply each outlet individually to the existing segment. 100387 */ 100388 100389 100390function isCommandWithOutlets(command) { 100391 return typeof command === 'object' && command != null && command.outlets; 100392} 100393 100394function tree(oldRoot, oldSegmentGroup, newSegmentGroup, queryParams, fragment) { 100395 let qp = {}; 100396 100397 if (queryParams) { 100398 forEach(queryParams, (value, name) => { 100399 qp[name] = Array.isArray(value) ? value.map(v => `${v}`) : `${value}`; 100400 }); 100401 } 100402 100403 let rootCandidate; 100404 100405 if (oldRoot === oldSegmentGroup) { 100406 rootCandidate = newSegmentGroup; 100407 } else { 100408 rootCandidate = replaceSegment(oldRoot, oldSegmentGroup, newSegmentGroup); 100409 } 100410 100411 const newRoot = createRoot(squashSegmentGroup(rootCandidate)); 100412 return new UrlTree(newRoot, qp, fragment); 100413} 100414/** 100415 * Replaces the `oldSegment` which is located in some child of the `current` with the `newSegment`. 100416 * This also has the effect of creating new `UrlSegmentGroup` copies to update references. This 100417 * shouldn't be necessary but the fallback logic for an invalid ActivatedRoute in the creation uses 100418 * the Router's current url tree. If we don't create new segment groups, we end up modifying that 100419 * value. 100420 */ 100421 100422 100423function replaceSegment(current, oldSegment, newSegment) { 100424 const children = {}; 100425 forEach(current.children, (c, outletName) => { 100426 if (c === oldSegment) { 100427 children[outletName] = newSegment; 100428 } else { 100429 children[outletName] = replaceSegment(c, oldSegment, newSegment); 100430 } 100431 }); 100432 return new UrlSegmentGroup(current.segments, children); 100433} 100434 100435class Navigation { 100436 constructor(isAbsolute, numberOfDoubleDots, commands) { 100437 this.isAbsolute = isAbsolute; 100438 this.numberOfDoubleDots = numberOfDoubleDots; 100439 this.commands = commands; 100440 100441 if (isAbsolute && commands.length > 0 && isMatrixParams(commands[0])) { 100442 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4003 100443 /* RuntimeErrorCode.ROOT_SEGMENT_MATRIX_PARAMS */ 100444 , NG_DEV_MODE$8 && 'Root segment cannot have matrix parameters'); 100445 } 100446 100447 const cmdWithOutlet = commands.find(isCommandWithOutlets); 100448 100449 if (cmdWithOutlet && cmdWithOutlet !== last(commands)) { 100450 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4004 100451 /* RuntimeErrorCode.MISPLACED_OUTLETS_COMMAND */ 100452 , NG_DEV_MODE$8 && '{outlets:{}} has to be the last command'); 100453 } 100454 } 100455 100456 toRoot() { 100457 return this.isAbsolute && this.commands.length === 1 && this.commands[0] == '/'; 100458 } 100459 100460} 100461/** Transforms commands to a normalized `Navigation` */ 100462 100463 100464function computeNavigation(commands) { 100465 if (typeof commands[0] === 'string' && commands.length === 1 && commands[0] === '/') { 100466 return new Navigation(true, 0, commands); 100467 } 100468 100469 let numberOfDoubleDots = 0; 100470 let isAbsolute = false;
100471 const res = commands.reduce((res, cmd, cmdIdx) => { 100472 if (typeof cmd === 'object' && cmd != null) { 100473 if (cmd.outlets) { 100474 const outlets = {}; 100475 forEach(cmd.outlets, (commands, name) => { 100476 outlets[name] = typeof commands === 'string' ? commands.split('/') : commands; 100477 }); 100478 return [...res, { 100479 outlets 100480 }]; 100481 } 100482 100483 if (cmd.segmentPath) { 100484 return [...res, cmd.segmentPath]; 100485 } 100486 } 100487 100488 if (!(typeof cmd === 'string')) { 100489 return [...res, cmd]; 100490 } 100491 100492 if (cmdIdx === 0) { 100493 cmd.split('/').forEach((urlPart, partIndex) => { 100494 if (partIndex == 0 && urlPart === '.') {// skip './a' 100495 } else if (partIndex == 0 && urlPart === '') { 100496 // '/a' 100497 isAbsolute = true; 100498 } else if (urlPart === '..') { 100499 // '../a' 100500 numberOfDoubleDots++; 100501 } else if (urlPart != '') { 100502 res.push(urlPart); 100503 } 100504 }); 100505 return res; 100506 } 100507 100508 return [...res, cmd]; 100509 }, []); 100510 return new Navigation(isAbsolute, numberOfDoubleDots, res); 100511} 100512 100513class Position { 100514 constructor(segmentGroup, processChildren, index) { 100515 this.segmentGroup = segmentGroup; 100516 this.processChildren = processChildren; 100517 this.index = index; 100518 } 100519 100520} 100521 100522function findStartingPositionForTargetGroup(nav, root, target) { 100523 if (nav.isAbsolute) { 100524 return new Position(root, true, 0); 100525 } 100526 100527 if (!target) { 100528 // `NaN` is used only to maintain backwards compatibility with incorrectly mocked 100529 // `ActivatedRouteSnapshot` in tests. In prior versions of this code, the position here was 100530 // determined based on an internal property that was rarely mocked, resulting in `NaN`. In 100531 // reality, this code path should _never_ be touched since `target` is not allowed to be falsey. 100532 return new Position(root, false, NaN); 100533 } 100534 100535 if (target.parent === null) { 100536 return new Position(target, true, 0); 100537 } 100538 100539 const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1; 100540 const index = target.segments.length - 1 + modifier; 100541 return createPositionApplyingDoubleDots(target, index, nav.numberOfDoubleDots); 100542} 100543 100544function findStartingPosition(nav, tree, segmentGroup, lastPathIndex) { 100545 if (nav.isAbsolute) { 100546 return new Position(tree.root, true, 0); 100547 } 100548 100549 if (lastPathIndex === -1) { 100550 // Pathless ActivatedRoute has _lastPathIndex === -1 but should not process children 100551 // see issue #26224, #13011, #35687 100552 // However, if the ActivatedRoute is the root we should process children like above. 100553 const processChildren = segmentGroup === tree.root; 100554 return new Position(segmentGroup, processChildren, 0); 100555 } 100556 100557 const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1; 100558 const index = lastPathIndex + modifier; 100559 return createPositionApplyingDoubleDots(segmentGroup, index, nav.numberOfDoubleDots); 100560} 100561 100562function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) { 100563 let g = group; 100564 let ci = index; 100565 let dd = numberOfDoubleDots; 100566 100567 while (dd > ci) { 100568 dd -= ci; 100569 g = g.parent; 100570 100571 if (!g) { 100572 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4005 100573 /* RuntimeErrorCode.INVALID_DOUBLE_DOTS */ 100574 , NG_DEV_MODE$8 && 'Invalid number of \'../\''); 100575 } 100576 100577 ci = g.segments.length; 100578 } 100579 100580 return new Position(g, false, ci - dd); 100581} 100582 100583function getOutlets(commands) { 100584 if (isCommandWithOutlets(commands[0])) { 100585 return commands[0].outlets; 100586 } 100587 100588 return { 100589 [PRIMARY_OUTLET]: commands 100590 }; 100591} 100592 100593function updateSegmentGroup(segmentGroup, startIndex, commands) { 100594 if (!segmentGroup) { 100595 segmentGroup = new UrlSegmentGroup([], {}); 100596 } 100597 100598 if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) { 100599 return updateSegmentGroupChildren(segmentGroup, startIndex, commands); 100600 } 100601 100602 const m = prefixedWith(segmentGroup, startIndex, commands); 100603 const slicedCommands = commands.slice(m.commandIndex); 100604 100605 if (m.match && m.pathIndex < segmentGroup.segments.length) { 100606 const g = new UrlSegmentGroup(segmentGroup.segments.slice(0, m.pathIndex), {}); 100607 g.children[PRIMARY_OUTLET] = new UrlSegmentGroup(segmentGroup.segments.slice(m.pathIndex), segmentGroup.children); 100608 return updateSegmentGroupChildren(g, 0, slicedCommands); 100609 } else if (m.match && slicedCommands.length === 0) { 100610 return new UrlSegmentGroup(segmentGroup.segments, {}); 100611 } else if (m.match && !segmentGroup.hasChildren()) { 100612 return createNewSegmentGroup(segmentGroup, startIndex, commands); 100613 } else if (m.match) { 100614 return updateSegmentGroupChildren(segmentGroup, 0, slicedCommands); 100615 } else { 100616 return createNewSegmentGroup(segmentGroup, startIndex, commands); 100617 } 100618} 100619 100620function updateSegmentGroupChildren(segmentGroup, startIndex, commands) { 100621 if (commands.length === 0) { 100622 return new UrlSegmentGroup(segmentGroup.segments, {}); 100623 } else { 100624 const outlets = getOutlets(commands); 100625 const children = {};
100626 forEach(outlets, (commands, outlet) => { 100627 if (typeof commands === 'string') { 100628 commands = [commands]; 100629 } 100630 100631 if (commands !== null) { 100632 children[outlet] = updateSegmentGroup(segmentGroup.children[outlet], startIndex, commands); 100633 } 100634 }); 100635 forEach(segmentGroup.children, (child, childOutlet) => { 100636 if (outlets[childOutlet] === undefined) { 100637 children[childOutlet] = child; 100638 } 100639 }); 100640 return new UrlSegmentGroup(segmentGroup.segments, children); 100641 } 100642} 100643 100644function prefixedWith(segmentGroup, startIndex, commands) { 100645 let currentCommandIndex = 0; 100646 let currentPathIndex = startIndex; 100647 const noMatch = { 100648 match: false, 100649 pathIndex: 0, 100650 commandIndex: 0 100651 }; 100652 100653 while (currentPathIndex < segmentGroup.segments.length) { 100654 if (currentCommandIndex >= commands.length) return noMatch; 100655 const path = segmentGroup.segments[currentPathIndex]; 100656 const command = commands[currentCommandIndex]; // Do not try to consume command as part of the prefixing if it has outlets because it can 100657 // contain outlets other than the one being processed. Consuming the outlets command would 100658 // result in other outlets being ignored. 100659 100660 if (isCommandWithOutlets(command)) { 100661 break; 100662 } 100663 100664 const curr = `${command}`; 100665 const next = currentCommandIndex < commands.length - 1 ? commands[currentCommandIndex + 1] : null; 100666 if (currentPathIndex > 0 && curr === undefined) break; 100667 100668 if (curr && next && typeof next === 'object' && next.outlets === undefined) { 100669 if (!compare(curr, next, path)) return noMatch; 100670 currentCommandIndex += 2; 100671 } else { 100672 if (!compare(curr, {}, path)) return noMatch; 100673 currentCommandIndex++; 100674 } 100675 100676 currentPathIndex++; 100677 } 100678 100679 return { 100680 match: true, 100681 pathIndex: currentPathIndex, 100682 commandIndex: currentCommandIndex 100683 }; 100684} 100685 100686function createNewSegmentGroup(segmentGroup, startIndex, commands) { 100687 const paths = segmentGroup.segments.slice(0, startIndex); 100688 let i = 0; 100689 100690 while (i < commands.length) { 100691 const command = commands[i]; 100692 100693 if (isCommandWithOutlets(command)) { 100694 const children = createNewSegmentChildren(command.outlets); 100695 return new UrlSegmentGroup(paths, children); 100696 } // if we start with an object literal, we need to reuse the path part from the segment 100697 100698 100699 if (i === 0 && isMatrixParams(commands[0])) { 100700 const p = segmentGroup.segments[startIndex]; 100701 paths.push(new UrlSegment(p.path, stringify(commands[0]))); 100702 i++; 100703 continue; 100704 } 100705 100706 const curr = isCommandWithOutlets(command) ? command.outlets[PRIMARY_OUTLET] : `${command}`; 100707 const next = i < commands.length - 1 ? commands[i + 1] : null; 100708 100709 if (curr && next && isMatrixParams(next)) { 100710 paths.push(new UrlSegment(curr, stringify(next))); 100711 i += 2; 100712 } else { 100713 paths.push(new UrlSegment(curr, {})); 100714 i++; 100715 } 100716 } 100717 100718 return new UrlSegmentGroup(paths, {}); 100719} 100720 100721function createNewSegmentChildren(outlets) { 100722 const children = {}; 100723 forEach(outlets, (commands, outlet) => { 100724 if (typeof commands === 'string') { 100725 commands = [commands]; 100726 } 100727 100728 if (commands !== null) { 100729 children[outlet] = createNewSegmentGroup(new UrlSegmentGroup([], {}), 0, commands); 100730 } 100731 }); 100732 return children; 100733} 100734 100735function stringify(params) { 100736 const res = {}; 100737 forEach(params, (v, k) => res[k] = `${v}`); 100738 return res; 100739} 100740 100741function compare(path, params, segment) { 100742 return path == segment.path && shallowEqual(params, segment.parameters); 100743} 100744/** 100745 * @license 100746 * Copyright Google LLC All Rights Reserved. 100747 * 100748 * Use of this source code is governed by an MIT-style license that can be 100749 * found in the LICENSE file at https://angular.io/license 100750 */ 100751 100752/** 100753 * Base for events the router goes through, as opposed to events tied to a specific 100754 * route. Fired one time for any given navigation. 100755 * 100756 * The following code shows how a class subscribes to router events. 100757 * 100758 * ```ts 100759 * import {Event, RouterEvent, Router} from '@angular/router'; 100760 * 100761 * class MyService { 100762 * constructor(public router: Router) { 100763 * router.events.pipe( 100764 * filter((e: Event): e is RouterEvent => e instanceof RouterEvent) 100765 * ).subscribe((e: RouterEvent) => { 100766 * // Do something 100767 * }); 100768 * } 100769 * } 100770 * ``` 100771 * 100772 * @see `Event` 100773 * @see [Router events summary](guide/router-reference#router-events) 100774 * @publicApi 100775 */ 100776 100777 100778class RouterEvent { 100779 constructor( 100780 /** A unique ID that the router assigns to every router navigation. */ 100781 id, 100782 /** The URL that is the destination for this navigation. */ 100783 url) { 100784 this.id = id; 100785 this.url = url; 100786 } 100787 100788} 100789/** 100790 * An event triggered when a navigation starts. 100791 * 100792 * @publicApi 100793 */ 100794 100795 100796class NavigationStart extends RouterEvent { 100797 constructor( 100798 /** @docsNotRequired */ 100799 id, 100800 /** @docsNotRequired */ 100801 url, 100802 /** @docsNotRequired */ 100803 navigationTrigger = 'imperative', 100804 /** @docsNotRequired */ 100805 restoredState = null) { 100806 super(id, url); 100807 this.type = 0 100808 /* EventType.NavigationStart */ 100809 ; 100810 this.navigationTrigger = navigationTrigger; 100811 this.restoredState = restoredState; 100812 } 100813 /** @docsNotRequired */ 100814 100815 100816 toString() { 100817 return `NavigationStart(id: ${this.id}, url: '${this.url}')`; 100818 } 100819 100820} 100821/** 100822 * An event triggered when a navigation ends successfully. 100823 * 100824 * @see `NavigationStart` 100825 * @see `NavigationCancel` 100826 * @see `NavigationError` 100827 * 100828 * @publicApi 100829 */ 100830 100831 100832class NavigationEnd extends RouterEvent { 100833 constructor( 100834 /** @docsNotRequired */ 100835 id, 100836 /** @docsNotRequired */ 100837 url, 100838 /** @docsNotRequired */ 100839 urlAfterRedirects) { 100840 super(id, url); 100841 this.urlAfterRedirects = urlAfterRedirects; 100842 this.type = 1 100843 /* EventType.NavigationEnd */ 100844 ; 100845 } 100846 /** @docsNotRequired */ 100847 100848 100849 toString() { 100850 return `NavigationEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}')`; 100851 } 100852 100853} 100854/** 100855 * An event triggered when a navigation is canceled, directly or indirectly. 100856 * This can happen for several reasons including when a route guard 100857 * returns `false` or initiates a redirect by returning a `UrlTree`. 100858 * 100859 * @see `NavigationStart` 100860 * @see `NavigationEnd` 100861 * @see `NavigationError` 100862 * 100863 * @publicApi 100864 */ 100865 100866 100867class NavigationCancel extends RouterEvent { 100868 constructor( 100869 /** @docsNotRequired */ 100870 id, 100871 /** @docsNotRequired */ 100872 url, 100873 /** 100874 * A description of why the navigation was cancelled. For debug purposes only. Use `code` 100875 * instead for a stable cancellation reason that can be used in production. 100876 */ 100877 reason, 100878 /** 100879 * A code to indicate why the navigation was canceled. This cancellation code is stable for 100880 * the reason and can be relied on whereas the `reason` string could change and should not be 100881 * used in production. 100882 */ 100883 code) { 100884 super(id, url); 100885 this.reason = reason; 100886 this.code = code; 100887 this.type = 2 100888 /* EventType.NavigationCancel */ 100889 ; 100890 } 100891 /** @docsNotRequired */ 100892 100893 100894 toString() { 100895 return `NavigationCancel(id: ${this.id}, url: '${this.url}')`; 100896 } 100897 100898} 100899/** 100900 * An event triggered when a navigation fails due to an unexpected error. 100901 * 100902 * @see `NavigationStart` 100903 * @see `NavigationEnd` 100904 * @see `NavigationCancel` 100905 * 100906 * @publicApi 100907 */ 100908 100909 100910class NavigationError extends RouterEvent { 100911 constructor( 100912 /** @docsNotRequired */ 100913 id, 100914 /** @docsNotRequired */ 100915 url, 100916 /** @docsNotRequired */ 100917 error, 100918 /** 100919 * The target of the navigation when the error occurred. 100920 * 100921 * Note that this can be `undefined` because an error could have occurred before the 100922 * `RouterStateSnapshot` was created for the navigation. 100923 */ 100924 target) { 100925 super(id, url); 100926 this.error = error; 100927 this.target = target; 100928 this.type = 3 100929 /* EventType.NavigationError */ 100930 ; 100931 } 100932 /** @docsNotRequired */ 100933 100934 100935 toString() { 100936 return `NavigationError(id: ${this.id}, url: '${this.url}', error: ${this.error})`; 100937 } 100938 100939} 100940/** 100941 * An event triggered when routes are recognized. 100942 * 100943 * @publicApi 100944 */ 100945 100946 100947class RoutesRecognized extends RouterEvent { 100948 constructor( 100949 /** @docsNotRequired */ 100950 id, 100951 /** @docsNotRequired */ 100952 url, 100953 /** @docsNotRequired */ 100954 urlAfterRedirects, 100955 /** @docsNotRequired */ 100956 state) { 100957 super(id, url); 100958 this.urlAfterRedirects = urlAfterRedirects; 100959 this.state = state; 100960 this.type = 4 100961 /* EventType.RoutesRecognized */ 100962 ; 100963 } 100964 /** @docsNotRequired */ 100965 100966 100967 toString() { 100968 return `RoutesRecognized(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; 100969 } 100970 100971} 100972/** 100973 * An event triggered at the start of the Guard phase of routing. 100974 * 100975 * @see `GuardsCheckEnd` 100976 * 100977 * @publicApi 100978 */ 100979 100980 100981class GuardsCheckStart extends RouterEvent { 100982 constructor( 100983 /** @docsNotRequired */ 100984 id, 100985 /** @docsNotRequired */ 100986 url, 100987 /** @docsNotRequired */ 100988 urlAfterRedirects, 100989 /** @docsNotRequired */ 100990 state) { 100991 super(id, url); 100992 this.urlAfterRedirects = urlAfterRedirects; 100993 this.state = state; 100994 this.type = 7 100995 /* EventType.GuardsCheckStart */ 100996 ; 100997 } 100998 100999 toString() { 101000 return `GuardsCheckStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; 101001 } 101002 101003} 101004/** 101005 * An event triggered at the end of the Guard phase of routing. 101006 * 101007 * @see `GuardsCheckStart` 101008 * 101009 * @publicApi 101010 */ 101011 101012 101013class GuardsCheckEnd extends RouterEvent { 101014 constructor( 101015 /** @docsNotRequired */ 101016 id, 101017 /** @docsNotRequired */ 101018 url, 101019 /** @docsNotRequired */ 101020 urlAfterRedirects, 101021 /** @docsNotRequired */ 101022 state, 101023 /** @docsNotRequired */ 101024 shouldActivate) { 101025 super(id, url); 101026 this.urlAfterRedirects = urlAfterRedirects; 101027 this.state = state; 101028 this.shouldActivate = shouldActivate; 101029 this.type = 8 101030 /* EventType.GuardsCheckEnd */ 101031 ; 101032 } 101033 101034 toString() { 101035 return `GuardsCheckEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state}, shouldActivate: ${this.shouldActivate})`; 101036 } 101037 101038} 101039/** 101040 * An event triggered at the start of the Resolve phase of routing. 101041 * 101042 * Runs in the "resolve" phase whether or not there is anything to resolve. 101043 * In future, may change to only run when there are things to be resolved. 101044 * 101045 * @see `ResolveEnd` 101046 * 101047 * @publicApi 101048 */ 101049 101050 101051class ResolveStart extends RouterEvent { 101052 constructor( 101053 /** @docsNotRequired */ 101054 id, 101055 /** @docsNotRequired */ 101056 url, 101057 /** @docsNotRequired */ 101058 urlAfterRedirects, 101059 /** @docsNotRequired */ 101060 state) { 101061 super(id, url); 101062 this.urlAfterRedirects = urlAfterRedirects; 101063 this.state = state; 101064 this.type = 5 101065 /* EventType.ResolveStart */ 101066 ; 101067 } 101068 101069 toString() { 101070 return `ResolveStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; 101071 } 101072 101073} 101074/** 101075 * An event triggered at the end of the Resolve phase of routing. 101076 * @see `ResolveStart`. 101077 * 101078 * @publicApi 101079 */ 101080 101081 101082class ResolveEnd extends RouterEvent { 101083 constructor( 101084 /** @docsNotRequired */ 101085 id, 101086 /** @docsNotRequired */ 101087 url, 101088 /** @docsNotRequired */ 101089 urlAfterRedirects, 101090 /** @docsNotRequired */ 101091 state) { 101092 super(id, url); 101093 this.urlAfterRedirects = urlAfterRedirects; 101094 this.state = state; 101095 this.type = 6 101096 /* EventType.ResolveEnd */ 101097 ; 101098 } 101099 101100 toString() { 101101 return `ResolveEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; 101102 } 101103 101104} 101105/** 101106 * An event triggered before lazy loading a route configuration. 101107 * 101108 * @see `RouteConfigLoadEnd` 101109 * 101110 * @publicApi 101111 */ 101112 101113 101114class RouteConfigLoadStart { 101115 constructor( 101116 /** @docsNotRequired */ 101117 route) { 101118 this.route = route; 101119 this.type = 9 101120 /* EventType.RouteConfigLoadStart */ 101121 ; 101122 } 101123 101124 toString() { 101125 return `RouteConfigLoadStart(path: ${this.route.path})`; 101126 } 101127 101128} 101129/** 101130 * An event triggered when a route has been lazy loaded. 101131 * 101132 * @see `RouteConfigLoadStart`
101133 * 101134 * @publicApi 101135 */ 101136 101137 101138class RouteConfigLoadEnd { 101139 constructor( 101140 /** @docsNotRequired */ 101141 route) { 101142 this.route = route; 101143 this.type = 10 101144 /* EventType.RouteConfigLoadEnd */ 101145 ; 101146 } 101147 101148 toString() { 101149 return `RouteConfigLoadEnd(path: ${this.route.path})`; 101150 } 101151 101152} 101153/** 101154 * An event triggered at the start of the child-activation 101155 * part of the Resolve phase of routing. 101156 * @see `ChildActivationEnd` 101157 * @see `ResolveStart` 101158 * 101159 * @publicApi 101160 */ 101161 101162 101163class ChildActivationStart { 101164 constructor( 101165 /** @docsNotRequired */ 101166 snapshot) { 101167 this.snapshot = snapshot; 101168 this.type = 11 101169 /* EventType.ChildActivationStart */ 101170 ; 101171 } 101172 101173 toString() { 101174 const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ''; 101175 return `ChildActivationStart(path: '${path}')`; 101176 } 101177 101178} 101179/** 101180 * An event triggered at the end of the child-activation part 101181 * of the Resolve phase of routing. 101182 * @see `ChildActivationStart` 101183 * @see `ResolveStart` 101184 * @publicApi 101185 */ 101186 101187 101188class ChildActivationEnd { 101189 constructor( 101190 /** @docsNotRequired */ 101191 snapshot) { 101192 this.snapshot = snapshot; 101193 this.type = 12 101194 /* EventType.ChildActivationEnd */ 101195 ; 101196 } 101197 101198 toString() { 101199 const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ''; 101200 return `ChildActivationEnd(path: '${path}')`; 101201 } 101202 101203} 101204/** 101205 * An event triggered at the start of the activation part 101206 * of the Resolve phase of routing. 101207 * @see `ActivationEnd` 101208 * @see `ResolveStart` 101209 * 101210 * @publicApi 101211 */ 101212 101213 101214class ActivationStart { 101215 constructor( 101216 /** @docsNotRequired */ 101217 snapshot) { 101218 this.snapshot = snapshot; 101219 this.type = 13 101220 /* EventType.ActivationStart */ 101221 ; 101222 } 101223 101224 toString() { 101225 const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ''; 101226 return `ActivationStart(path: '${path}')`; 101227 } 101228 101229} 101230/** 101231 * An event triggered at the end of the activation part 101232 * of the Resolve phase of routing. 101233 * @see `ActivationStart` 101234 * @see `ResolveStart` 101235 * 101236 * @publicApi 101237 */ 101238 101239 101240class ActivationEnd { 101241 constructor( 101242 /** @docsNotRequired */ 101243 snapshot) { 101244 this.snapshot = snapshot; 101245 this.type = 14 101246 /* EventType.ActivationEnd */ 101247 ; 101248 } 101249 101250 toString() { 101251 const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ''; 101252 return `ActivationEnd(path: '${path}')`; 101253 } 101254 101255} 101256/** 101257 * An event triggered by scrolling. 101258 * 101259 * @publicApi 101260 */ 101261 101262 101263class Scroll { 101264 constructor( 101265 /** @docsNotRequired */ 101266 routerEvent, 101267 /** @docsNotRequired */ 101268 position, 101269 /** @docsNotRequired */ 101270 anchor) { 101271 this.routerEvent = routerEvent; 101272 this.position = position; 101273 this.anchor = anchor; 101274 this.type = 15 101275 /* EventType.Scroll */ 101276 ; 101277 } 101278 101279 toString() { 101280 const pos = this.position ? `${this.position[0]}, ${this.position[1]}` : null; 101281 return `Scroll(anchor: '${this.anchor}', position: '${pos}')`; 101282 } 101283 101284} 101285 101286function stringifyEvent(routerEvent) { 101287 if (!('type' in routerEvent)) { 101288 return `Unknown Router Event: ${routerEvent.constructor.name}`; 101289 } 101290 101291 switch (routerEvent.type) { 101292 case 14 101293 /* EventType.ActivationEnd */ 101294 : 101295 return `ActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`; 101296 101297 case 13 101298 /* EventType.ActivationStart */ 101299 : 101300 return `ActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`; 101301 101302 case 12 101303 /* EventType.ChildActivationEnd */ 101304 : 101305 return `ChildActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`; 101306 101307 case 11 101308 /* EventType.ChildActivationStart */ 101309 : 101310 return `ChildActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`; 101311 101312 case 8 101313 /* EventType.GuardsCheckEnd */ 101314 : 101315 return `GuardsCheckEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state}, shouldActivate: ${routerEvent.shouldActivate})`; 101316 101317 case 7 101318 /* EventType.GuardsCheckStart */ 101319 : 101320 return `GuardsCheckStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`; 101321 101322 case 2 101323 /* EventType.NavigationCancel */ 101324 : 101325 return `NavigationCancel(id: ${routerEvent.id}, url: '${routerEvent.url}')`; 101326 101327 case 1 101328 /* EventType.NavigationEnd */ 101329 : 101330 return `NavigationEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}')`; 101331 101332 case 3 101333 /* EventType.NavigationError */ 101334 : 101335 return `NavigationError(id: ${routerEvent.id}, url: '${routerEvent.url}', error: ${routerEvent.error})`; 101336 101337 case 0 101338 /* EventType.NavigationStart */ 101339 : 101340 return `NavigationStart(id: ${routerEvent.id}, url: '${routerEvent.url}')`; 101341 101342 case 6 101343 /* EventType.ResolveEnd */ 101344 : 101345 return `ResolveEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}
101345', state: ${routerEvent.state})`; 101346 101347 case 5 101348 /* EventType.ResolveStart */ 101349 : 101350 return `ResolveStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`; 101351 101352 case 10 101353 /* EventType.RouteConfigLoadEnd */ 101354 : 101355 return `RouteConfigLoadEnd(path: ${routerEvent.route.path})`; 101356 101357 case 9 101358 /* EventType.RouteConfigLoadStart */ 101359 : 101360 return `RouteConfigLoadStart(path: ${routerEvent.route.path})`; 101361 101362 case 4 101363 /* EventType.RoutesRecognized */ 101364 : 101365 return `RoutesRecognized(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`; 101366 101367 case 15 101368 /* EventType.Scroll */ 101369 : 101370 const pos = routerEvent.position ? `${routerEvent.position[0]}, ${routerEvent.position[1]}` : null; 101371 return `Scroll(anchor: '${routerEvent.anchor}', position: '${pos}')`; 101372 } 101373} 101374/** 101375 * @license 101376 * Copyright Google LLC All Rights Reserved. 101377 * 101378 * Use of this source code is governed by an MIT-style license that can be 101379 * found in the LICENSE file at https://angular.io/license 101380 */ 101381 101382 101383class Tree { 101384 constructor(root) { 101385 this._root = root; 101386 } 101387 101388 get root() { 101389 return this._root.value; 101390 } 101391 /** 101392 * @internal 101393 */ 101394 101395 101396 parent(t) { 101397 const p = this.pathFromRoot(t); 101398 return p.length > 1 ? p[p.length - 2] : null; 101399 } 101400 /** 101401 * @internal 101402 */ 101403 101404 101405 children(t) { 101406 const n = findNode(t, this._root); 101407 return n ? n.children.map(t => t.value) : []; 101408 } 101409 /** 101410 * @internal 101411 */ 101412 101413 101414 firstChild(t) { 101415 const n = findNode(t, this._root); 101416 return n && n.children.length > 0 ? n.children[0].value : null; 101417 } 101418 /** 101419 * @internal 101420 */ 101421 101422 101423 siblings(t) { 101424 const p = findPath(t, this._root); 101425 if (p.length < 2) return []; 101426 const c = p[p.length - 2].children.map(c => c.value); 101427 return c.filter(cc => cc !== t); 101428 } 101429 /** 101430 * @internal 101431 */ 101432 101433 101434 pathFromRoot(t) { 101435 return findPath(t, this._root).map(s => s.value); 101436 } 101437 101438} // DFS for the node matching the value 101439 101440 101441function findNode(value, node) { 101442 if (value === node.value) return node; 101443 101444 for (const child of node.children) { 101445 const node = findNode(value, child); 101446 if (node) return node; 101447 } 101448 101449 return null; 101450} // Return the path to the node with the given value using DFS 101451 101452 101453function findPath(value, node) { 101454 if (value === node.value) return [node]; 101455 101456 for (const child of node.children) { 101457 const path = findPath(value, child); 101458 101459 if (path.length) { 101460 path.unshift(node); 101461 return path; 101462 } 101463 } 101464 101465 return []; 101466} 101467 101468class TreeNode { 101469 constructor(value, children) { 101470 this.value = value; 101471 this.children = children; 101472 } 101473 101474 toString() { 101475 return `TreeNode(${this.value})`; 101476 } 101477 101478} // Return the list of T indexed by outlet name 101479 101480 101481function nodeChildrenAsMap(node) { 101482 const map = {}; 101483 101484 if (node) { 101485 node.children.forEach(child => map[child.value.outlet] = child); 101486 } 101487 101488 return map; 101489} 101490/** 101491 * @license 101492 * Copyright Google LLC All Rights Reserved. 101493 * 101494 * Use of this source code is governed by an MIT-style license that can be 101495 * found in the LICENSE file at https://angular.io/license 101496 */ 101497 101498/** 101499 * Represents the state of the router as a tree of activated routes. 101500 * 101501 * @usageNotes 101502 * 101503 * Every node in the route tree is an `ActivatedRoute` instance 101504 * that knows about the "consumed" URL segments, the extracted parameters, 101505 * and the resolved data. 101506 * Use the `ActivatedRoute` properties to traverse the tree from any node. 101507 * 101508 * The following fragment shows how a component gets the root node 101509 * of the current state to establish its own route tree: 101510 * 101511 * ``` 101512 * @Component({templateUrl:'template.html'}) 101513 * class MyComponent { 101514 * constructor(router: Router) { 101515 * const state: RouterState = router.routerState; 101516 * const root: ActivatedRoute = state.root; 101517 * const child = root.firstChild; 101518 * const id: Observable<string> = child.params.map(p => p.id); 101519 * //... 101520 * } 101521 * } 101522 * ``` 101523 * 101524 * @see `ActivatedRoute` 101525 * @see [Getting route information](guide/router#getting-route-information) 101526 * 101527 * @publicApi 101528 */ 101529 101530 101531class RouterState extends Tree { 101532 /** @internal */ 101533 constructor(root, 101534 /** The current snapshot of the router state */ 101535 snapshot) { 101536 super(root); 101537 this.snapshot = snapshot; 101538 setRouterState(this, root); 101539 } 101540 101541 toString() { 101542 return this.snapshot.toString(); 101543 } 101544 101545} 101546 101547function createEmptyState(urlTree, rootComponent) { 101548 const snapshot = createEmptyStateSnapshot(urlTree, rootComponent); 101549 const emptyUrl = new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject([new UrlSegment('', {})]); 101550 const emptyParams = new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject({}); 101551 const emptyData = new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject({}); 101552 const emptyQueryParams = new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject({}); 101553 const fragment = new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject(''); 101554 const activated = new ActivatedRoute(emptyUrl, emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, snapshot.root); 101555 activated.snapshot = snapshot.root; 101556 return new RouterState(new TreeNode(activated, []), snapshot); 101557} 101558 101559function createEmptyStateSnapshot(urlTree, rootComponent) { 101560 const emptyParams = {}; 101561 const emptyData = {}; 101562 const emptyQueryParams = {}; 101563 const fragment = ''; 101564 const activated = new ActivatedRouteSnapshot([], emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, null, urlTree.root, -1, {}); 101565 return new RouterStateSnapshot('', new TreeNode(activated, [])); 101566} 101567/** 101568 * Provides access to information about a route associated with a component 101569 * that is loaded in an outlet. 101570 * Use to traverse the `RouterState` tree and extract information from nodes. 101571 * 101572 * The following example shows how to construct a component using information from a 101573 * currently activated route. 101574 *
101575 * Note: the observables in this class only emit when the current and previous values differ based 101576 * on shallow equality. For example, changing deeply nested properties in resolved `data` will not 101577 * cause the `ActivatedRoute.data` `Observable` to emit a new value. 101578 * 101579 * {@example router/activated-route/module.ts region="activated-route" 101580 * header="activated-route.component.ts"} 101581 * 101582 * @see [Getting route information](guide/router#getting-route-information) 101583 * 101584 * @publicApi 101585 */ 101586 101587 101588class ActivatedRoute { 101589 /** @internal */ 101590 constructor( 101591 /** An observable of the URL segments matched by this route. */ 101592 url, 101593 /** An observable of the matrix parameters scoped to this route. */ 101594 params, 101595 /** An observable of the query parameters shared by all the routes. */ 101596 queryParams, 101597 /** An observable of the URL fragment shared by all the routes. */ 101598 fragment, 101599 /** An observable of the static and resolved data of this route. */ 101600 data, 101601 /** The outlet name of the route, a constant. */ 101602 outlet, 101603 /** The component of the route, a constant. */ 101604 component, futureSnapshot) { 101605 this.url = url; 101606 this.params = params; 101607 this.queryParams = queryParams; 101608 this.fragment = fragment; 101609 this.data = data; 101610 this.outlet = outlet; 101611 this.component = component; 101612 /** An Observable of the resolved route title */ 101613 101614 this.title = this.data?.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(d => d[RouteTitleKey])) ?? (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(undefined); 101615 this._futureSnapshot = futureSnapshot; 101616 } 101617 /** The configuration used to match this route. */ 101618 101619 101620 get routeConfig() { 101621 return this._futureSnapshot.routeConfig; 101622 } 101623 /** The root of the router state. */ 101624 101625 101626 get root() { 101627 return this._routerState.root; 101628 } 101629 /** The parent of this route in the router state tree. */ 101630 101631 101632 get parent() { 101633 return this._routerState.parent(this); 101634 } 101635 /** The first child of this route in the router state tree. */ 101636 101637 101638 get firstChild() { 101639 return this._routerState.firstChild(this); 101640 } 101641 /** The children of this route in the router state tree. */ 101642 101643 101644 get children() { 101645 return this._routerState.children(this); 101646 } 101647 /** The path from the root of the router state tree to this route. */ 101648 101649 101650 get pathFromRoot() { 101651 return this._routerState.pathFromRoot(this); 101652 } 101653 /** 101654 * An Observable that contains a map of the required and optional parameters 101655 * specific to the route. 101656 * The map supports retrieving single and multiple values from the same parameter. 101657 */ 101658 101659 101660 get paramMap() { 101661 if (!this._paramMap) { 101662 this._paramMap = this.params.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(p => convertToParamMap(p))); 101663 } 101664 101665 return this._paramMap; 101666 } 101667 /** 101668 * An Observable that contains a map of the query parameters available to all routes. 101669 * The map supports retrieving single and multiple values from the query parameter. 101670 */ 101671 101672 101673 get queryParamMap() { 101674 if (!this._queryParamMap) { 101675 this._queryParamMap = this.queryParams.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(p => convertToParamMap(p))); 101676 } 101677 101678 return this._queryParamMap; 101679 } 101680 101681 toString() { 101682 return this.snapshot ? this.snapshot.toString() : `Future(${this._futureSnapshot})`; 101683 } 101684 101685} 101686/** 101687 * Returns the inherited params, data, and resolve for a given route. 101688 * By default, this only inherits values up to the nearest path-less or component-less route. 101689 * @internal 101690 */ 101691 101692 101693function inheritedParamsDataResolve(route, paramsInheritanceStrategy = 'emptyOnly') { 101694 const pathFromRoot = route.pathFromRoot; 101695 let inheritingStartingFrom = 0; 101696 101697 if (paramsInheritanceStrategy !== 'always') { 101698 inheritingStartingFrom = pathFromRoot.length - 1; 101699 101700 while (inheritingStartingFrom >= 1) { 101701 const current = pathFromRoot[inheritingStartingFrom]; 101702 const parent = pathFromRoot[inheritingStartingFrom - 1]; // current route is an empty path => inherits its parent's params and data 101703 101704 if (current.routeConfig && current.routeConfig.path === '') { 101705 inheritingStartingFrom--; // parent is componentless => current route should inherit its params and data 101706 } else if (!parent.component) { 101707 inheritingStartingFrom--; 101708 } else { 101709 break; 101710 } 101711 } 101712 } 101713 101714 return flattenInherited(pathFromRoot.slice(inheritingStartingFrom)); 101715} 101716/** @internal */ 101717 101718 101719function flattenInherited(pathFromRoot) { 101720 return pathFromRoot.reduce((res, curr) => { 101721 const params = { ...res.params, 101722 ...curr.params 101723 }; 101724 const data = { ...res.data, 101725 ...curr.data 101726 }; 101727 const resolve = { ...curr.data, 101728 ...res.resolve, 101729 ...curr.routeConfig?.data, 101730 ...curr._resolvedData 101731 }; 101732 return { 101733 params, 101734 data, 101735 resolve 101736 }; 101737 }, { 101738 params: {}, 101739 data: {}, 101740 resolve: {} 101741 }); 101742} 101743/** 101744 * @description 101745 * 101746 * Contains the information about a route associated with a component loaded in an 101747 * outlet at a particular moment in time. ActivatedRouteSnapshot can also be used to 101748 * traverse the router state tree. 101749 * 101750 * The following example initializes a component with route information extracted 101751 * from the snapshot of the root node at the time of creation. 101752 * 101753 * ``` 101754 * @Component({templateUrl:'./my-component.html'}) 101755 * class MyComponent { 101756 * constructor(route: ActivatedRoute) { 101757 * const id: string = route.snapshot.params.id; 101758 * const url: string = route.snapshot.url.join(''); 101759 * const user = route.snapshot.data.user; 101760 * } 101761 * } 101762 * ``` 101763 * 101764 * @publicApi 101765 */ 101766 101767 101768class ActivatedRouteSnapshot { 101769 /** @internal */ 101770 constructor( 101771 /** The URL segments matched by this route */ 101772 url, 101773 /** 101774 * The matrix parameters scoped to this route. 101775 * 101776 * You can compute all params (or data) in the router state or to get params outside 101777 * of an activated component by traversing the `RouterState` tree as in the following 101778 * example: 101779 * ```
101780 * collectRouteParams(router: Router) { 101781 * let params = {}; 101782 * let stack: ActivatedRouteSnapshot[] = [router.routerState.snapshot.root]; 101783 * while (stack.length > 0) { 101784 * const route = stack.pop()!; 101785 * params = {...params, ...route.params}; 101786 * stack.push(...route.children); 101787 * } 101788 * return params; 101789 * } 101790 * ``` 101791 */ 101792 params, 101793 /** The query parameters shared by all the routes */ 101794 queryParams, 101795 /** The URL fragment shared by all the routes */ 101796 fragment, 101797 /** The static and resolved data of this route */ 101798 data, 101799 /** The outlet name of the route */ 101800 outlet, 101801 /** The component of the route */ 101802 component, routeConfig, urlSegment, lastPathIndex, resolve, correctedLastPathIndex) { 101803 this.url = url; 101804 this.params = params; 101805 this.queryParams = queryParams; 101806 this.fragment = fragment; 101807 this.data = data; 101808 this.outlet = outlet; 101809 this.component = component; 101810 /** The resolved route title */ 101811 101812 this.title = this.data?.[RouteTitleKey]; 101813 this.routeConfig = routeConfig; 101814 this._urlSegment = urlSegment; 101815 this._lastPathIndex = lastPathIndex; 101816 this._correctedLastPathIndex = correctedLastPathIndex ?? lastPathIndex; 101817 this._resolve = resolve; 101818 } 101819 /** The root of the router state */ 101820 101821 101822 get root() { 101823 return this._routerState.root; 101824 } 101825 /** The parent of this route in the router state tree */ 101826 101827 101828 get parent() { 101829 return this._routerState.parent(this); 101830 } 101831 /** The first child of this route in the router state tree */ 101832 101833 101834 get firstChild() { 101835 return this._routerState.firstChild(this); 101836 } 101837 /** The children of this route in the router state tree */ 101838 101839 101840 get children() { 101841 return this._routerState.children(this); 101842 } 101843 /** The path from the root of the router state tree to this route */ 101844 101845 101846 get pathFromRoot() { 101847 return this._routerState.pathFromRoot(this); 101848 } 101849 101850 get paramMap() { 101851 if (!this._paramMap) { 101852 this._paramMap = convertToParamMap(this.params); 101853 } 101854 101855 return this._paramMap; 101856 } 101857 101858 get queryParamMap() { 101859 if (!this._queryParamMap) { 101860 this._queryParamMap = convertToParamMap(this.queryParams); 101861 } 101862 101863 return this._queryParamMap; 101864 } 101865 101866 toString() { 101867 const url = this.url.map(segment => segment.toString()).join('/'); 101868 const matched = this.routeConfig ? this.routeConfig.path : ''; 101869 return `Route(url:'${url}', path:'${matched}')`; 101870 } 101871 101872} 101873/** 101874 * @description 101875 * 101876 * Represents the state of the router at a moment in time. 101877 * 101878 * This is a tree of activated route snapshots. Every node in this tree knows about 101879 * the "consumed" URL segments, the extracted parameters, and the resolved data. 101880 * 101881 * The following example shows how a component is initialized with information 101882 * from the snapshot of the root node's state at the time of creation. 101883 * 101884 * ``` 101885 * @Component({templateUrl:'template.html'}) 101886 * class MyComponent { 101887 * constructor(router: Router) { 101888 * const state: RouterState = router.routerState; 101889 * const snapshot: RouterStateSnapshot = state.snapshot; 101890 * const root: ActivatedRouteSnapshot = snapshot.root; 101891 * const child = root.firstChild; 101892 * const id: Observable<string> = child.params.map(p => p.id); 101893 * //... 101894 * } 101895 * } 101896 * ``` 101897 * 101898 * @publicApi 101899 */ 101900 101901 101902class RouterStateSnapshot extends Tree { 101903 /** @internal */ 101904 constructor( 101905 /** The url from which this snapshot was created */ 101906 url, root) { 101907 super(root); 101908 this.url = url; 101909 setRouterState(this, root); 101910 } 101911 101912 toString() { 101913 return serializeNode(this._root); 101914 } 101915 101916} 101917 101918function setRouterState(state, node) { 101919 node.value._routerState = state; 101920 node.children.forEach(c => setRouterState(state, c)); 101921} 101922 101923function serializeNode(node) { 101924 const c = node.children.length > 0 ? ` { ${node.children.map(serializeNode).join(', ')} } ` : ''; 101925 return `${node.value}${c}`; 101926} 101927/** 101928 * The expectation is that the activate route is created with the right set of parameters. 101929 * So we push new values into the observables only when they are not the initial values. 101930 * And we detect that by checking if the snapshot field is set. 101931 */ 101932 101933 101934function advanceActivatedRoute(route) { 101935 if (route.snapshot) { 101936 const currentSnapshot = route.snapshot; 101937 const nextSnapshot = route._futureSnapshot; 101938 route.snapshot = nextSnapshot; 101939 101940 if (!shallowEqual(currentSnapshot.queryParams, nextSnapshot.queryParams)) { 101941 route.queryParams.next(nextSnapshot.queryParams); 101942 } 101943 101944 if (currentSnapshot.fragment !== nextSnapshot.fragment) { 101945 route.fragment.next(nextSnapshot.fragment); 101946 } 101947 101948 if (!shallowEqual(currentSnapshot.params, nextSnapshot.params)) { 101949 route.params.next(nextSnapshot.params); 101950 } 101951 101952 if (!shallowEqualArrays(currentSnapshot.url, nextSnapshot.url)) { 101953 route.url.next(nextSnapshot.url); 101954 } 101955 101956 if (!shallowEqual(currentSnapshot.data, nextSnapshot.data)) { 101957 route.data.next(nextSnapshot.data); 101958 } 101959 } else { 101960 route.snapshot = route._futureSnapshot; // this is for resolved data 101961 101962 route.data.next(route._futureSnapshot.data); 101963 } 101964} 101965 101966function equalParamsAndUrlSegments(a, b) { 101967 const equalUrlParams = shallowEqual(a.params, b.params) && equalSegments(a.url, b.url); 101968 const parentsMismatch = !a.parent !== !b.parent; 101969 return equalUrlParams && !parentsMismatch && (!a.parent || equalParamsAndUrlSegments(a.parent, b.parent)); 101970} 101971/** 101972 * @license 101973 * Copyright Google LLC All Rights Reserved. 101974 * 101975 * Use of this source code is governed by an MIT-style license that can be 101976 * found in the LICENSE file at https://angular.io/license 101977 */ 101978 101979 101980function createRouterState(routeReuseStrategy, curr, prevState) { 101981 const root = createNode(routeReuseStrategy, curr._root, prevState ? prevState._root : undefined); 101982 return new RouterState(root, curr); 101983} 101984 101985function createNode(routeReuseStrategy, curr, prevState) { 101986 // reuse an activated route that is currently displayed on the screen 101987 if (prevState && routeReuseStrategy.shouldReuseRoute(curr.value, prevState.value.snapshot)) { 101988 const value = prevState.value; 101989 value._futureSnapshot = curr.value; 101990 const children = createOrReuseChildren(routeReuseStrategy, curr, prevState); 101991 return new TreeNode(value, children); 101992 } else { 101993 if (routeReuseStrategy.shouldAttach(curr.value)) { 101994 // retrieve an activated route that is used to be displayed, but is not currently displayed 101995 const detachedRouteHandle = routeReuseStrategy.retrieve(curr.value); 101996 101997 if (detachedRouteHandle !== null) { 101998 const tree = detachedRouteHandle.route; 101999 tree.value._futureSnapshot = curr.value; 102000 tree.children = curr.children.map(c => createNode(routeReuseStrategy, c)); 102001 return tree; 102002 } 102003 } 102004 102005 const value = createActivatedRoute(curr.value); 102006 const children = curr.children.map(c => createNode(routeReuseStrategy, c)); 102007 return new TreeNode(value, children); 102008 } 102009} 102010 102011function createOrReuseChildren(routeReuseStrategy, curr, prevState) { 102012 return curr.children.map(child => { 102013 for (const p of prevState.children) { 102014 if (routeReuseStrategy.shouldReuseRoute(child.value, p.value.snapshot)) { 102015 return createNode(routeReuseStrategy, child, p); 102016 } 102017 } 102018 102019 return createNode(routeReuseStrategy, child); 102020 }); 102021} 102022 102023function createActivatedRoute(c) { 102024 return new ActivatedRoute(new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject(c.url), new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject(c.params), new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject(c.queryParams), new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject(c.fragment), new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject(c.data), c.outlet, c.component, c); 102025} 102026/** 102027 * @license 102028 * Copyright Google LLC All Rights Reserved. 102029 * 102030 * Use of this source code is governed by an MIT-style license that can be 102031 * found in the LICENSE file at https://angular.io/license 102032 */ 102033 102034 102035const NAVIGATION_CANCELING_ERROR = 'ngNavigationCancelingError'; 102036 102037function redirectingNavigationError(urlSerializer, redirect) { 102038 const { 102039 redirectTo, 102040 navigationBehaviorOptions 102041 } = isUrlTree(redirect) ? { 102042 redirectTo: redirect, 102043 navigationBehaviorOptions: undefined 102044 } : redirect; 102045 const error = navigationCancelingError(ngDevMode && `Redirecting to "${urlSerializer.serialize(redirectTo)}"`, 0 102046 /* NavigationCancellationCode.Redirect */ 102047 , redirect); 102048 error.url = redirectTo; 102049 error.navigationBehaviorOptions = navigationBehaviorOptions; 102050 return error; 102051} 102052 102053function navigationCancelingError(message, code, redirectUrl) { 102054 const error = new Error('NavigationCancelingError: ' + (message || '')); 102055 error[NAVIGATION_CANCELING_ERROR] = true; 102056 error.cancellationCode = code; 102057 102058 if (redirectUrl) { 102059 error.url = redirectUrl; 102060 } 102061 102062 return error; 102063} 102064 102065function isRedirectingNavigationCancelingError$1(error) { 102066 return isNavigationCancelingError$1(error) && isUrlTree(error.url); 102067} 102068 102069function isNavigationCancelingError$1(error) { 102070 return error && error[NAVIGATION_CANCELING_ERROR]; 102071} 102072/** 102073 * @license 102074 * Copyright Google LLC All Rights Reserved. 102075 * 102076 * Use of this source code is governed by an MIT-style license that can be 102077 * found in the LICENSE file at https://angular.io/license 102078 */ 102079 102080/** 102081 * Store contextual information about a `RouterOutlet` 102082 * 102083 * @publicApi 102084 */ 102085 102086 102087class OutletContext { 102088 constructor() { 102089 this.outlet = null; 102090 this.route = null; 102091 /** 102092 * @deprecated Passing a resolver to retrieve a component factory is not required and is 102093 * deprecated since v14. 102094 */ 102095 102096 this.resolver = null; 102097 this.injector = null; 102098 this.children = new ChildrenOutletContexts(); 102099 this.attachRef = null; 102100 } 102101 102102} 102103/** 102104 * Store contextual information about the children (= nested) `RouterOutlet` 102105 * 102106 * @publicApi 102107 */ 102108 102109 102110class ChildrenOutletContexts { 102111 constructor() { 102112 // contexts for child outlets, by name. 102113 this.contexts = new Map(); 102114 } 102115 /** Called when a `RouterOutlet` directive is instantiated */ 102116 102117 102118 onChildOutletCreated(childName, outlet) {
102119 const context = this.getOrCreateContext(childName); 102120 context.outlet = outlet; 102121 this.contexts.set(childName, context); 102122 } 102123 /** 102124 * Called when a `RouterOutlet` directive is destroyed. 102125 * We need to keep the context as the outlet could be destroyed inside a NgIf and might be 102126 * re-created later. 102127 */ 102128 102129 102130 onChildOutletDestroyed(childName) { 102131 const context = this.getContext(childName); 102132 102133 if (context) { 102134 context.outlet = null; 102135 context.attachRef = null; 102136 } 102137 } 102138 /** 102139 * Called when the corresponding route is deactivated during navigation. 102140 * Because the component get destroyed, all children outlet are destroyed. 102141 */ 102142 102143 102144 onOutletDeactivated() { 102145 const contexts = this.contexts; 102146 this.contexts = new Map(); 102147 return contexts; 102148 } 102149 102150 onOutletReAttached(contexts) { 102151 this.contexts = contexts; 102152 } 102153 102154 getOrCreateContext(childName) { 102155 let context = this.getContext(childName); 102156 102157 if (!context) { 102158 context = new OutletContext(); 102159 this.contexts.set(childName, context); 102160 } 102161 102162 return context; 102163 } 102164 102165 getContext(childName) { 102166 return this.contexts.get(childName) || null; 102167 } 102168 102169} 102170 102171ChildrenOutletContexts.ɵfac = function ChildrenOutletContexts_Factory(t) { 102172 return new (t || ChildrenOutletContexts)(); 102173}; 102174 102175ChildrenOutletContexts.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 102176 token: ChildrenOutletContexts, 102177 factory: ChildrenOutletContexts.ɵfac, 102178 providedIn: 'root' 102179}); 102180 102181(function () { 102182 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ChildrenOutletContexts, [{ 102183 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 102184 args: [{ 102185 providedIn: 'root' 102186 }] 102187 }], null, null); 102188})(); 102189/** 102190 * @license 102191 * Copyright Google LLC All Rights Reserved. 102192 * 102193 * Use of this source code is governed by an MIT-style license that can be 102194 * found in the LICENSE file at https://angular.io/license 102195 */ 102196 102197 102198const NG_DEV_MODE$7 = typeof ngDevMode === 'undefined' || ngDevMode; 102199/** 102200 * @description 102201 * 102202 * Acts as a placeholder that Angular dynamically fills based on the current router state. 102203 * 102204 * Each outlet can have a unique name, determined by the optional `name` attribute. 102205 * The name cannot be set or changed dynamically. If not set, default value is "primary". 102206 * 102207 * ``` 102208 * <router-outlet></router-outlet> 102209 * <router-outlet name='left'></router-outlet> 102210 * <router-outlet name='right'></router-outlet> 102211 * ``` 102212 * 102213 * Named outlets can be the targets of secondary routes. 102214 * The `Route` object for a secondary route has an `outlet` property to identify the target outlet: 102215 * 102216 * `{path: <base-path>, component: <component>, outlet: <target_outlet_name>}` 102217 * 102218 * Using named outlets and secondary routes, you can target multiple outlets in 102219 * the same `RouterLink` directive. 102220 * 102221 * The router keeps track of separate branches in a navigation tree for each named outlet and 102222 * generates a representation of that tree in the URL. 102223 * The URL for a secondary route uses the following syntax to specify both the primary and secondary 102224 * routes at the same time: 102225 * 102226 * `http://base-path/primary-route-path(outlet-name:route-path)` 102227 * 102228 * A router outlet emits an activate event when a new component is instantiated, 102229 * deactivate event when a component is destroyed. 102230 * An attached event emits when the `RouteReuseStrategy` instructs the outlet to reattach the 102231 * subtree, and the detached event emits when the `RouteReuseStrategy` instructs the outlet to 102232 * detach the subtree. 102233 * 102234 * ``` 102235 * <router-outlet 102236 * (activate)='onActivate($event)' 102237 * (deactivate)='onDeactivate($event)' 102238 * (attach)='onAttach($event)' 102239 * (detach)='onDetach($event)'></router-outlet> 102240 * ``` 102241 * 102242 * @see [Routing tutorial](guide/router-tutorial-toh#named-outlets "Example of a named 102243 * outlet and secondary route configuration"). 102244 * @see `RouterLink` 102245 * @see `Route` 102246 * @ngModule RouterModule 102247 * 102248 * @publicApi 102249 */ 102250 102251class RouterOutlet { 102252 constructor(parentContexts, location, name, changeDetector, environmentInjector) { 102253 this.parentContexts = parentContexts; 102254 this.location = location; 102255 this.changeDetector = changeDetector; 102256 this.environmentInjector = environmentInjector; 102257 this.activated = null; 102258 this._activatedRoute = null; 102259 this.activateEvents = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); 102260 this.deactivateEvents = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); 102261 /** 102262 * Emits an attached component instance when the `RouteReuseStrategy` instructs to re-attach a 102263 * previously detached subtree. 102264 **/ 102265 102266 this.attachEvents = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); 102267 /** 102268 * Emits a detached component instance when the `RouteReuseStrategy` instructs to detach the 102269 * subtree. 102270 */ 102271 102272 this.detachEvents = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); 102273 this.name = name || PRIMARY_OUTLET; 102274 parentContexts.onChildOutletCreated(this.name, this); 102275 } 102276 /** @nodoc */ 102277 102278 102279 ngOnDestroy() { 102280 // Ensure that the registered outlet is this one before removing it on the context. 102281 if (this.parentContexts.getContext(this.name)?.outlet === this) { 102282 this.parentContexts.onChildOutletDestroyed(this.name); 102283 } 102284 } 102285 /** @nodoc */ 102286 102287 102288 ngOnInit() { 102289 if (!this.activated) { 102290 // If the outlet was not instantiated at the time the route got activated
102290we need to populate 102291 // the outlet when it is initialized (ie inside a NgIf) 102292 const context = this.parentContexts.getContext(this.name); 102293 102294 if (context && context.route) { 102295 if (context.attachRef) { 102296 // `attachRef` is populated when there is an existing component to mount 102297 this.attach(context.attachRef, context.route); 102298 } else { 102299 // otherwise the component defined in the configuration is created 102300 this.activateWith(context.route, context.injector); 102301 } 102302 } 102303 } 102304 } 102305 102306 get isActivated() { 102307 return !!this.activated; 102308 } 102309 /** 102310 * @returns The currently activated component instance. 102311 * @throws An error if the outlet is not activated. 102312 */ 102313 102314 102315 get component() { 102316 if (!this.activated) throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4012 102317 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */ 102318 , NG_DEV_MODE$7 && 'Outlet is not activated'); 102319 return this.activated.instance; 102320 } 102321 102322 get activatedRoute() { 102323 if (!this.activated) throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4012 102324 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */ 102325 , NG_DEV_MODE$7 && 'Outlet is not activated'); 102326 return this._activatedRoute; 102327 } 102328 102329 get activatedRouteData() { 102330 if (this._activatedRoute) { 102331 return this._activatedRoute.snapshot.data; 102332 } 102333 102334 return {}; 102335 } 102336 /** 102337 * Called when the `RouteReuseStrategy` instructs to detach the subtree 102338 */ 102339 102340 102341 detach() { 102342 if (!this.activated) throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4012 102343 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */ 102344 , NG_DEV_MODE$7 && 'Outlet is not activated'); 102345 this.location.detach(); 102346 const cmp = this.activated; 102347 this.activated = null; 102348 this._activatedRoute = null; 102349 this.detachEvents.emit(cmp.instance); 102350 return cmp; 102351 } 102352 /** 102353 * Called when the `RouteReuseStrategy` instructs to re-attach a previously detached subtree 102354 */ 102355 102356 102357 attach(ref, activatedRoute) { 102358 this.activated = ref; 102359 this._activatedRoute = activatedRoute; 102360 this.location.insert(ref.hostView); 102361 this.attachEvents.emit(ref.instance); 102362 } 102363 102364 deactivate() { 102365 if (this.activated) { 102366 const c = this.component; 102367 this.activated.destroy(); 102368 this.activated = null; 102369 this._activatedRoute = null; 102370 this.deactivateEvents.emit(c); 102371 } 102372 } 102373 102374 activateWith(activatedRoute, resolverOrInjector) { 102375 if (this.isActivated) { 102376 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4013 102377 /* RuntimeErrorCode.OUTLET_ALREADY_ACTIVATED */ 102378 , NG_DEV_MODE$7 && 'Cannot activate an already activated outlet'); 102379 } 102380 102381 this._activatedRoute = activatedRoute; 102382 const location = this.location; 102383 const snapshot = activatedRoute._futureSnapshot; 102384 const component = snapshot.component; 102385 const childContexts = this.parentContexts.getOrCreateContext(this.name).children; 102386 const injector = new OutletInjector(activatedRoute, childContexts, location.injector); 102387 102388 if (resolverOrInjector && isComponentFactoryResolver(resolverOrInjector)) { 102389 const factory = resolverOrInjector.resolveComponentFactory(component); 102390 this.activated = location.createComponent(factory, location.length, injector); 102391 } else { 102392 const environmentInjector = resolverOrInjector ?? this.environmentInjector; 102393 this.activated = location.createComponent(component, { 102394 index: location.length, 102395 injector, 102396 environmentInjector 102397 }); 102398 } // Calling `markForCheck` to make sure we will run the change detection when the 102399 // `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component. 102400 102401 102402 this.changeDetector.markForCheck(); 102403 this.activateEvents.emit(this.activated.instance); 102404 } 102405 102406} 102407 102408RouterOutlet.ɵfac = function RouterOutlet_Factory(t) { 102409 return new (t || RouterOutlet)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ChildrenOutletContexts), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinjectAttribute"]('name'), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.EnvironmentInjector)); 102410}; 102411 102412RouterOutlet.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 102413 type: RouterOutlet, 102414 selectors: [["router-outlet"]], 102415 outputs: { 102416 activateEvents: "activate", 102417 deactivateEvents: "deactivate", 102418 attachEvents: "attach", 102419 detachEvents: "detach" 102420 }, 102421 exportAs: ["outlet"], 102422 standalone: true 102423}); 102424 102425(function () { 102426 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterOutlet, [{ 102427 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 102428 args: [{ 102429 selector: 'router-outlet', 102430 exportAs: 'outlet', 102431 standalone: true 102432 }] 102433 }], function () { 102434 return [{ 102435 type: ChildrenOutletContexts 102436 }, {
102437 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ViewContainerRef 102438 }, { 102439 type: undefined, 102440 decorators: [{ 102441 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Attribute, 102442 args: ['name'] 102443 }] 102444 }, { 102445 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef 102446 }, { 102447 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.EnvironmentInjector 102448 }]; 102449 }, { 102450 activateEvents: [{ 102451 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output, 102452 args: ['activate'] 102453 }], 102454 deactivateEvents: [{ 102455 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output, 102456 args: ['deactivate'] 102457 }], 102458 attachEvents: [{ 102459 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output, 102460 args: ['attach'] 102461 }], 102462 detachEvents: [{ 102463 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output, 102464 args: ['detach'] 102465 }] 102466 }); 102467})(); 102468 102469class OutletInjector { 102470 constructor(route, childContexts, parent) { 102471 this.route = route; 102472 this.childContexts = childContexts; 102473 this.parent = parent; 102474 } 102475 102476 get(token, notFoundValue) { 102477 if (token === ActivatedRoute) { 102478 return this.route; 102479 } 102480 102481 if (token === ChildrenOutletContexts) { 102482 return this.childContexts; 102483 } 102484 102485 return this.parent.get(token, notFoundValue); 102486 } 102487 102488} 102489 102490function isComponentFactoryResolver(item) { 102491 return !!item.resolveComponentFactory; 102492} 102493/** 102494 * @license 102495 * Copyright Google LLC All Rights Reserved. 102496 * 102497 * Use of this source code is governed by an MIT-style license that can be 102498 * found in the LICENSE file at https://angular.io/license 102499 */ 102500 102501/** 102502 * This component is used internally within the router to be a placeholder when an empty 102503 * router-outlet is needed. For example, with a config such as: 102504 * 102505 * `{path: 'parent', outlet: 'nav', children: [...]}` 102506 * 102507 * In order to render, there needs to be a component on this config, which will default 102508 * to this `EmptyOutletComponent`. 102509 */ 102510 102511 102512class ɵEmptyOutletComponent {} 102513 102514ɵEmptyOutletComponent.ɵfac = function ɵEmptyOutletComponent_Factory(t) { 102515 return new (t || ɵEmptyOutletComponent)(); 102516}; 102517 102518ɵEmptyOutletComponent.ɵcmp = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineComponent"]({ 102519 type: ɵEmptyOutletComponent, 102520 selectors: [["ng-component"]], 102521 standalone: true, 102522 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵStandaloneFeature"]], 102523 decls: 1, 102524 vars: 0, 102525 template: function ɵEmptyOutletComponent_Template(rf, ctx) { 102526 if (rf & 1) { 102527 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵelement"](0, "router-outlet"); 102528 } 102529 }, 102530 dependencies: [RouterOutlet], 102531 encapsulation: 2 102532}); 102533 102534(function () { 102535 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](ɵEmptyOutletComponent, [{ 102536 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Component, 102537 args: [{ 102538 template: `<router-outlet></router-outlet>`, 102539 imports: [RouterOutlet], 102540 standalone: true 102541 }] 102542 }], null, null); 102543})(); 102544/** 102545 * @license 102546 * Copyright Google LLC All Rights Reserved. 102547 * 102548 * Use of this source code is governed by an MIT-style license that can be 102549 * found in the LICENSE file at https://angular.io/license 102550 */ 102551 102552/** 102553 * Creates an `EnvironmentInjector` if the `Route` has providers and one does not already exist 102554 * and returns the injector. Otherwise, if the `Route` does not have `providers`, returns the 102555 * `currentInjector`. 102556 * 102557 * @param route The route that might have providers 102558 * @param currentInjector The parent injector of the `Route` 102559 */ 102560 102561 102562function getOrCreateRouteInjectorIfNeeded(route, currentInjector) { 102563 if (route.providers && !route._injector) { 102564 route._injector = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.createEnvironmentInjector)(route.providers, currentInjector, `Route: ${route.path}`); 102565 } 102566 102567 return route._injector ?? currentInjector; 102568} 102569 102570function getLoadedRoutes(route) { 102571 return route._loadedRoutes; 102572} 102573 102574function getLoadedInjector(route) { 102575 return route._loadedInjector; 102576} 102577 102578function getLoadedComponent(route) { 102579 return route._loadedComponent; 102580} 102581 102582function getProvidersInjector(route) { 102583 return route._injector; 102584} 102585 102586function validateConfig(config, parentPath = '', requireStandaloneComponents = false) { 102587 // forEach doesn't iterate undefined values 102588 for (let i = 0; i < config.length; i++) { 102589 const route = config[i]; 102590 const fullPath = getFullPath(parentPath, route); 102591 validateNode(route, fullPath, requireStandaloneComponents); 102592 } 102593} 102594
102595function assertStandalone(fullPath, component) { 102596 if (component && !(0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisStandalone"])(component)) { 102597 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102598 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102599 , `Invalid configuration of route '${fullPath}'. The component must be standalone.`); 102600 } 102601} 102602 102603function validateNode(route, fullPath, requireStandaloneComponents) { 102604 if (typeof ngDevMode === 'undefined' || ngDevMode) { 102605 if (!route) { 102606 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102607 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102608 , ` 102609 Invalid configuration of route '${fullPath}': Encountered undefined route. 102610 The reason might be an extra comma. 102611 102612 Example: 102613 const routes: Routes = [ 102614 { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, 102615 { path: 'dashboard', component: DashboardComponent },, << two commas 102616 { path: 'detail/:id', component: HeroDetailComponent } 102617 ]; 102618 `); 102619 } 102620 102621 if (Array.isArray(route)) { 102622 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102623 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102624 , `Invalid configuration of route '${fullPath}': Array cannot be specified`); 102625 } 102626 102627 if (!route.redirectTo && !route.component && !route.loadComponent && !route.children && !route.loadChildren && route.outlet && route.outlet !== PRIMARY_OUTLET) { 102628 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102629 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102630 , `Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`); 102631 } 102632 102633 if (route.redirectTo && route.children) { 102634 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102635 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102636 , `Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`); 102637 } 102638 102639 if (route.redirectTo && route.loadChildren) { 102640 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102641 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102642 , `Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`); 102643 } 102644 102645 if (route.children && route.loadChildren) { 102646 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102647 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102648 , `Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`); 102649 } 102650 102651 if (route.redirectTo && (route.component || route.loadComponent)) { 102652 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102653 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102654 , `Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`); 102655 } 102656 102657 if (route.component && route.loadComponent) { 102658 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102659 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102660 , `Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`); 102661 } 102662 102663 if (route.redirectTo && route.canActivate) { 102664 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102665 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102666 , `Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation ` + `so canActivate will never be executed.`); 102667 } 102668 102669 if (route.path && route.matcher) { 102670 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102671 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102672 , `Invalid configuration of route '${fullPath}': path and matcher cannot be used together`); 102673 } 102674 102675 if (route.redirectTo === void 0 && !route.component && !route.loadComponent && !route.children && !route.loadChildren) { 102676 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102677 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102678 , `Invalid configuration of route '${fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`); 102679 } 102680 102681 if (route.path === void 0 && route.matcher === void 0) { 102682 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102683 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102684 , `Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`); 102685 } 102686 102687 if (typeof route.path === 'string' && route.path.charAt(0) === '/') { 102688 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102689 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102690 , `Invalid configuration of route '${fullPath}': path cannot start with a slash`); 102691 } 102692 102693 if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) { 102694 const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`; 102695 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4014 102696 /* RuntimeErrorCode.INVALID_ROUTE_CONFIG */ 102697 , `Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`); 102698 } 102699 102700 if (requireStandaloneComponents) { 102701 assertStandalone(fullPath, route.component); 102702 } 102703 } 102704 102705 if (route.children) { 102706 validateConfig(route.children, fullPath, requireStandaloneComponents); 102707 } 102708} 102709 102710function getFullPath(parentPath, currentRoute) { 102711 if (!currentRoute) { 102712 return parentPath; 102713 } 102714 102715 if (!parentPath && !currentRoute.path) { 102716 return ''; 102717 } else if (parentPath && !currentRoute.path) { 102718 return `${parentPath}/`; 102719 } else if (!parentPath && currentRoute.path) { 102720 return currentRoute.path; 102721 } else { 102722 return `${parentPath}/${currentRoute.path}`; 102723 } 102724} 102725/** 102726 * Makes a copy of the config and adds any default required properties. 102727 */ 102728 102729 102730function standardizeConfig(r) { 102731 const children = r.children && r.children.map(standardizeConfig); 102732 const c = children ? { ...r, 102733 children 102734 } : { ...r 102735 }; 102736 102737 if (!c.component && !c.loadComponent && (children || c.loadChildren) && c.outlet && c.outlet !== PRIMARY_OUTLET) { 102738 c.component = ɵEmptyOutletComponent; 102739 } 102740 102741 return c; 102742} 102743/** Returns the `route.outlet` or PRIMARY_OUTLET if none exists. */ 102744 102745 102746function getOutlet(route) { 102747 return route.outlet || PRIMARY_OUTLET; 102748} 102749/** 102750 * Sorts the `routes` such that the ones with an outlet matching `outletName` come first. 102751 * The order of the configs is otherwise preserved. 102752 */ 102753 102754 102755function sortByMatchingOutlets(routes, outletName) { 102756 const sortedConfig = routes.filter(r => getOutlet(r) === outletName); 102757 sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName)); 102758 return sortedConfig; 102759} 102760/** 102761 * Gets the first injector in the snapshot's parent tree. 102762 * 102763 * If the `Route` has a static list of providers, the returned injector will be the one created from 102764 * those. If it does not exist, the returned injector may come from the parents, which may be from a 102765 * loaded config or their static providers. 102766 * 102767 * Returns `null` if there is neither this nor any parents have a stored injector. 102768 * 102769 * Generally used for retrieving the injector to use for getting tokens for guards/resolvers and 102770 * also used for getting the correct injector to use for creating components. 102771 */ 102772 102773 102774function getClosestRouteInjector(snapshot) { 102775 if (!snapshot) return null; // If the current route has its own injector, which is created from the static providers on the 102776 // route itself, we should use that. Otherwise, we start at the parent since we do not want to 102777 // include the lazy loaded injector from this route. 102778 102779 if (snapshot.routeConfig?._injector) { 102780 return snapshot.routeConfig._injector; 102781 } 102782 102783 for (let s = snapshot.parent; s; s = s.parent) {
102784 const route = s.routeConfig; // Note that the order here is important. `_loadedInjector` stored on the route with 102785 // `loadChildren: () => NgModule` so it applies to child routes with priority. The `_injector` 102786 // is created from the static providers on that parent route, so it applies to the children as 102787 // well, but only if there is no lazy loaded NgModuleRef injector. 102788 102789 if (route?._loadedInjector) return route._loadedInjector; 102790 if (route?._injector) return route._injector; 102791 } 102792 102793 return null; 102794} 102795/** 102796 * @license 102797 * Copyright Google LLC All Rights Reserved. 102798 * 102799 * Use of this source code is governed by an MIT-style license that can be 102800 * found in the LICENSE file at https://angular.io/license 102801 */ 102802 102803 102804const activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent) => (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(t => { 102805 new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent).activate(rootContexts); 102806 return t; 102807}); 102808 102809class ActivateRoutes { 102810 constructor(routeReuseStrategy, futureState, currState, forwardEvent) { 102811 this.routeReuseStrategy = routeReuseStrategy; 102812 this.futureState = futureState; 102813 this.currState = currState; 102814 this.forwardEvent = forwardEvent; 102815 } 102816 102817 activate(parentContexts) { 102818 const futureRoot = this.futureState._root; 102819 const currRoot = this.currState ? this.currState._root : null; 102820 this.deactivateChildRoutes(futureRoot, currRoot, parentContexts); 102821 advanceActivatedRoute(this.futureState.root); 102822 this.activateChildRoutes(futureRoot, currRoot, parentContexts); 102823 } // De-activate the child route that are not re-used for the future state 102824 102825 102826 deactivateChildRoutes(futureNode, currNode, contexts) { 102827 const children = nodeChildrenAsMap(currNode); // Recurse on the routes active in the future state to de-activate deeper children 102828 102829 futureNode.children.forEach(futureChild => { 102830 const childOutletName = futureChild.value.outlet; 102831 this.deactivateRoutes(futureChild, children[childOutletName], contexts); 102832 delete children[childOutletName]; 102833 }); // De-activate the routes that will not be re-used 102834 102835 forEach(children, (v, childName) => { 102836 this.deactivateRouteAndItsChildren(v, contexts); 102837 }); 102838 } 102839 102840 deactivateRoutes(futureNode, currNode, parentContext) { 102841 const future = futureNode.value; 102842 const curr = currNode ? currNode.value : null; 102843 102844 if (future === curr) { 102845 // Reusing the node, check to see if the children need to be de-activated 102846 if (future.component) { 102847 // If we have a normal route, we need to go through an outlet. 102848 const context = parentContext.getContext(future.outlet); 102849 102850 if (context) { 102851 this.deactivateChildRoutes(futureNode, currNode, context.children); 102852 } 102853 } else { 102854 // if we have a componentless route, we recurse but keep the same outlet map. 102855 this.deactivateChildRoutes(futureNode, currNode, parentContext); 102856 } 102857 } else { 102858 if (curr) { 102859 // Deactivate the current route which will not be re-used 102860 this.deactivateRouteAndItsChildren(currNode, parentContext); 102861 } 102862 } 102863 } 102864 102865 deactivateRouteAndItsChildren(route, parentContexts) { 102866 // If there is no component, the Route is never attached to an outlet (because there is no 102867 // component to attach). 102868 if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) { 102869 this.detachAndStoreRouteSubtree(route, parentContexts); 102870 } else { 102871 this.deactivateRouteAndOutlet(route, parentContexts); 102872 } 102873 } 102874 102875 detachAndStoreRouteSubtree(route, parentContexts) { 102876 const context = parentContexts.getContext(route.value.outlet); 102877 const contexts = context && route.value.component ? context.children : parentContexts; 102878 const children = nodeChildrenAsMap(route); 102879 102880 for (const childOutlet of Object.keys(children)) { 102881 this.deactivateRouteAndItsChildren(children[childOutlet], contexts); 102882 } 102883 102884 if (context && context.outlet) { 102885 const componentRef = context.outlet.detach(); 102886 const contexts = context.children.onOutletDeactivated(); 102887 this.routeReuseStrategy.store(route.value.snapshot, { 102888 componentRef, 102889 route, 102890 contexts 102891 }); 102892 } 102893 } 102894 102895 deactivateRouteAndOutlet(route, parentContexts) { 102896 const context = parentContexts.getContext(route.value.outlet); // The context could be `null` if we are on a componentless route but there may still be 102897 // children that need deactivating. 102898 102899 const contexts = context && route.value.component ? context.children : parentContexts; 102900 const children = nodeChildrenAsMap(route); 102901 102902 for (const childOutlet of Object.keys(children)) { 102903 this.deactivateRouteAndItsChildren(children[childOutlet], contexts); 102904 } 102905 102906 if (context && context.outlet) { 102907 // Destroy the component 102908 context.outlet.deactivate(); // Destroy the contexts for all the outlets that were in the component 102909 102910 context.children.onOutletDeactivated(); // Clear the information about the attached component on the context but keep the reference to 102911 // the outlet. 102912 102913 context.attachRef = null; 102914 context.resolver = null; 102915 context.route = null; 102916 } 102917 } 102918 102919 activateChildRoutes(futureNode, currNode, contexts) { 102920 const children = nodeChildrenAsMap(currNode);
102921 futureNode.children.forEach(c => { 102922 this.activateRoutes(c, children[c.value.outlet], contexts); 102923 this.forwardEvent(new ActivationEnd(c.value.snapshot)); 102924 }); 102925 102926 if (futureNode.children.length) { 102927 this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot)); 102928 } 102929 } 102930 102931 activateRoutes(futureNode, currNode, parentContexts) { 102932 const future = futureNode.value; 102933 const curr = currNode ? currNode.value : null; 102934 advanceActivatedRoute(future); // reusing the node 102935 102936 if (future === curr) { 102937 if (future.component) { 102938 // If we have a normal route, we need to go through an outlet. 102939 const context = parentContexts.getOrCreateContext(future.outlet); 102940 this.activateChildRoutes(futureNode, currNode, context.children); 102941 } else { 102942 // if we have a componentless route, we recurse but keep the same outlet map. 102943 this.activateChildRoutes(futureNode, currNode, parentContexts); 102944 } 102945 } else { 102946 if (future.component) { 102947 // if we have a normal route, we need to place the component into the outlet and recurse. 102948 const context = parentContexts.getOrCreateContext(future.outlet); 102949 102950 if (this.routeReuseStrategy.shouldAttach(future.snapshot)) { 102951 const stored = this.routeReuseStrategy.retrieve(future.snapshot); 102952 this.routeReuseStrategy.store(future.snapshot, null); 102953 context.children.onOutletReAttached(stored.contexts); 102954 context.attachRef = stored.componentRef; 102955 context.route = stored.route.value; 102956 102957 if (context.outlet) { 102958 // Attach right away when the outlet has already been instantiated 102959 // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated 102960 context.outlet.attach(stored.componentRef, stored.route.value); 102961 } 102962 102963 advanceActivatedRoute(stored.route.value); 102964 this.activateChildRoutes(futureNode, null, context.children); 102965 } else { 102966 const injector = getClosestRouteInjector(future.snapshot); 102967 const cmpFactoryResolver = injector?.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__.ComponentFactoryResolver) ?? null; 102968 context.attachRef = null; 102969 context.route = future; 102970 context.resolver = cmpFactoryResolver; 102971 context.injector = injector; 102972 102973 if (context.outlet) { 102974 // Activate the outlet when it has already been instantiated 102975 // Otherwise it will get activated from its `ngOnInit` when instantiated 102976 context.outlet.activateWith(future, context.injector); 102977 } 102978 102979 this.activateChildRoutes(futureNode, null, context.children); 102980 } 102981 } else { 102982 // if we have a componentless route, we recurse but keep the same outlet map. 102983 this.activateChildRoutes(futureNode, null, parentContexts); 102984 } 102985 } 102986 } 102987 102988} 102989/** 102990 * @license 102991 * Copyright Google LLC All Rights Reserved. 102992 * 102993 * Use of this source code is governed by an MIT-style license that can be 102994 * found in the LICENSE file at https://angular.io/license 102995 */ 102996 102997 102998class CanActivate { 102999 constructor(path) { 103000 this.path = path; 103001 this.route = this.path[this.path.length - 1]; 103002 } 103003 103004} 103005 103006class CanDeactivate { 103007 constructor(component, route) { 103008 this.component = component; 103009 this.route = route; 103010 } 103011 103012} 103013 103014function getAllRouteGuards(future, curr, parentContexts) { 103015 const futureRoot = future._root; 103016 const currRoot = curr ? curr._root : null; 103017 return getChildRouteGuards(futureRoot, currRoot, parentContexts, [futureRoot.value]); 103018} 103019 103020function getCanActivateChild(p) { 103021 const canActivateChild = p.routeConfig ? p.routeConfig.canActivateChild : null; 103022 if (!canActivateChild || canActivateChild.length === 0) return null; 103023 return { 103024 node: p, 103025 guards: canActivateChild 103026 }; 103027} 103028 103029function getTokenOrFunctionIdentity(tokenOrFunction, injector) { 103030 const NOT_FOUND = Symbol(); 103031 const result = injector.get(tokenOrFunction, NOT_FOUND); 103032 103033 if (result === NOT_FOUND) { 103034 if (typeof tokenOrFunction === 'function' && !(0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisInjectable"])(tokenOrFunction)) { 103035 // We think the token is just a function so return it as-is 103036 return tokenOrFunction; 103037 } else { 103038 // This will throw the not found error 103039 return injector.get(tokenOrFunction); 103040 } 103041 } 103042 103043 return result; 103044} 103045 103046function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = { 103047 canDeactivateChecks: [], 103048 canActivateChecks: [] 103049}) { 103050 const prevChildren = nodeChildrenAsMap(currNode); // Process the children of the future route 103051
103052 futureNode.children.forEach(c => { 103053 getRouteGuards(c, prevChildren[c.value.outlet], contexts, futurePath.concat([c.value]), checks); 103054 delete prevChildren[c.value.outlet]; 103055 }); // Process any children left from the current route (not active for the future route) 103056 103057 forEach(prevChildren, (v, k) => deactivateRouteAndItsChildren(v, contexts.getContext(k), checks)); 103058 return checks; 103059} 103060 103061function getRouteGuards(futureNode, currNode, parentContexts, futurePath, checks = { 103062 canDeactivateChecks: [], 103063 canActivateChecks: [] 103064}) { 103065 const future = futureNode.value; 103066 const curr = currNode ? currNode.value : null; 103067 const context = parentContexts ? parentContexts.getContext(futureNode.value.outlet) : null; // reusing the node 103068 103069 if (curr && future.routeConfig === curr.routeConfig) { 103070 const shouldRun = shouldRunGuardsAndResolvers(curr, future, future.routeConfig.runGuardsAndResolvers); 103071 103072 if (shouldRun) { 103073 checks.canActivateChecks.push(new CanActivate(futurePath)); 103074 } else { 103075 // we need to set the data 103076 future.data = curr.data; 103077 future._resolvedData = curr._resolvedData; 103078 } // If we have a component, we need to go through an outlet. 103079 103080 103081 if (future.component) { 103082 getChildRouteGuards(futureNode, currNode, context ? context.children : null, futurePath, checks); // if we have a componentless route, we recurse but keep the same outlet map. 103083 } else { 103084 getChildRouteGuards(futureNode, currNode, parentContexts, futurePath, checks); 103085 } 103086 103087 if (shouldRun && context && context.outlet && context.outlet.isActivated) { 103088 checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, curr)); 103089 } 103090 } else { 103091 if (curr) { 103092 deactivateRouteAndItsChildren(currNode, context, checks); 103093 } 103094 103095 checks.canActivateChecks.push(new CanActivate(futurePath)); // If we have a component, we need to go through an outlet. 103096 103097 if (future.component) { 103098 getChildRouteGuards(futureNode, null, context ? context.children : null, futurePath, checks); // if we have a componentless route, we recurse but keep the same outlet map. 103099 } else { 103100 getChildRouteGuards(futureNode, null, parentContexts, futurePath, checks); 103101 } 103102 } 103103 103104 return checks; 103105} 103106 103107function shouldRunGuardsAndResolvers(curr, future, mode) { 103108 if (typeof mode === 'function') { 103109 return mode(curr, future); 103110 } 103111 103112 switch (mode) { 103113 case 'pathParamsChange': 103114 return !equalPath(curr.url, future.url); 103115 103116 case 'pathParamsOrQueryParamsChange': 103117 return !equalPath(curr.url, future.url) || !shallowEqual(curr.queryParams, future.queryParams); 103118 103119 case 'always': 103120 return true; 103121 103122 case 'paramsOrQueryParamsChange': 103123 return !equalParamsAndUrlSegments(curr, future) || !shallowEqual(curr.queryParams, future.queryParams); 103124 103125 case 'paramsChange': 103126 default: 103127 return !equalParamsAndUrlSegments(curr, future); 103128 } 103129} 103130 103131function deactivateRouteAndItsChildren(route, context, checks) { 103132 const children = nodeChildrenAsMap(route); 103133 const r = route.value; 103134 forEach(children, (node, childName) => { 103135 if (!r.component) { 103136 deactivateRouteAndItsChildren(node, context, checks); 103137 } else if (context) { 103138 deactivateRouteAndItsChildren(node, context.children.getContext(childName), checks); 103139 } else { 103140 deactivateRouteAndItsChildren(node, null, checks); 103141 } 103142 }); 103143 103144 if (!r.component) { 103145 checks.canDeactivateChecks.push(new CanDeactivate(null, r)); 103146 } else if (context && context.outlet && context.outlet.isActivated) { 103147 checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, r)); 103148 } else { 103149 checks.canDeactivateChecks.push(new CanDeactivate(null, r)); 103150 } 103151} 103152/** 103153 * @license 103154 * Copyright Google LLC All Rights Reserved. 103155 * 103156 * Use of this source code is governed by an MIT-style license that can be 103157 * found in the LICENSE file at https://angular.io/license 103158 */ 103159 103160/** 103161 * Simple function check, but generic so type inference will flow. Example: 103162 * 103163 * function product(a: number, b: number) { 103164 * return a * b; 103165 * } 103166 * 103167 * if (isFunction<product>(fn)) { 103168 * return fn(1, 2); 103169 * } else { 103170 * throw "Must provide the `product` function"; 103171 * } 103172 */ 103173 103174 103175function isFunction(v) { 103176 return typeof v === 'function'; 103177} 103178 103179function isBoolean(v) { 103180 return typeof v === 'boolean'; 103181} 103182 103183function isCanLoad(guard) { 103184 return guard && isFunction(guard.canLoad); 103185} 103186 103187function isCanActivate(guard) { 103188 return guard && isFunction(guard.canActivate); 103189} 103190 103191function isCanActivateChild(guard) { 103192 return guard && isFunction(guard.canActivateChild); 103193} 103194 103195function isCanDeactivate(guard) { 103196 return guard && isFunction(guard.canDeactivate); 103197} 103198 103199function isCanMatch(guard) { 103200 return guard && isFunction(guard.canMatch); 103201} 103202 103203function isRedirectingNavigationCancelingError(error) { 103204 return isNavigationCancelingError(error) && isUrlTree(error.url); 103205} 103206 103207function isNavigationCancelingError(error) { 103208 return error && error[NAVIGATION_CANCELING_ERROR]; 103209} 103210 103211function isEmptyError(e) { 103212 return e instanceof rxjs__WEBPACK_IMPORTED_MODULE_5__.EmptyError || e?.name === 'EmptyError'; 103213} 103214/** 103215 * @license 103216 * Copyright Google LLC All Rights Reserved. 103217 * 103218 * Use of this source code is governed by an MIT-style license that can be 103219 * found in the LICENSE file at https://angular.io/license 103220 */ 103221 103222 103223const INITIAL_VALUE = Symbol('INITIAL_VALUE'); 103224 103225function prioritizedGuardValue() { 103226 return (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(obs => { 103227 return (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.combineLatest)(obs.map(o => o.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.take)(1), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_9__.startWith)(INITIAL_VALUE)))).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(results => { 103228 for (const result of results) { 103229 if (result === true) { 103230 // If result is true, check the next one 103231 continue; 103232 } else if (result === INITIAL_VALUE) { 103233 // If guard has not finished, we need to stop processing. 103234 return INITIAL_VALUE; 103235 } else if (result === false || result instanceof UrlTree) { 103236 // Result finished and was not true. Return the result. 103237 // Note that we only allow false/UrlTree. Other values are considered invali
103237d and 103238 // ignored. 103239 return result; 103240 } 103241 } // Everything resolved to true. Return true. 103242 103243 103244 return true; 103245 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.filter)(item => item !== INITIAL_VALUE), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.take)(1)); 103246 }); 103247} 103248/** 103249 * @license 103250 * Copyright Google LLC All Rights Reserved. 103251 * 103252 * Use of this source code is governed by an MIT-style license that can be 103253 * found in the LICENSE file at https://angular.io/license 103254 */ 103255 103256 103257function checkGuards(injector, forwardEvent) { 103258 return (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(t => { 103259 const { 103260 targetSnapshot, 103261 currentSnapshot, 103262 guards: { 103263 canActivateChecks, 103264 canDeactivateChecks 103265 } 103266 } = t; 103267 103268 if (canDeactivateChecks.length === 0 && canActivateChecks.length === 0) { 103269 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({ ...t, 103270 guardsResult: true 103271 }); 103272 } 103273 103274 return runCanDeactivateChecks(canDeactivateChecks, targetSnapshot, currentSnapshot, injector).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(canDeactivate => { 103275 return canDeactivate && isBoolean(canDeactivate) ? runCanActivateChecks(targetSnapshot, canActivateChecks, injector, forwardEvent) : (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(canDeactivate); 103276 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(guardsResult => ({ ...t, 103277 guardsResult 103278 }))); 103279 }); 103280} 103281 103282function runCanDeactivateChecks(checks, futureRSS, currRSS, injector) { 103283 return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(checks).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(check => runCanDeactivate(check.component, check.route, currRSS, futureRSS, injector)), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)(result => { 103284 return result !== true; 103285 }, true)); 103286} 103287 103288function runCanActivateChecks(futureSnapshot, checks, injector, forwardEvent) { 103289 return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(checks).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.concatMap)(check => { 103290 return (0,rxjs__WEBPACK_IMPORTED_MODULE_14__.concat)(fireChildActivationStart(check.route.parent, forwardEvent), fireActivationStart(check.route, forwardEvent), runCanActivateChild(futureSnapshot, check.path, injector), runCanActivate(futureSnapshot, check.route, injector)); 103291 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)(result => { 103292 return result !== true; 103293 }, true)); 103294} 103295/** 103296 * This should fire off `ActivationStart` events for each route being activated at this 103297 * level. 103298 * In other words, if you're activating `a` and `b` below, `path` will contain the 103299 * `ActivatedRouteSnapshot`s for both and we will fire `ActivationStart` for both. Always 103300 * return 103301 * `true` so checks continue to run. 103302 */ 103303 103304 103305function fireActivationStart(snapshot, forwardEvent) { 103306 if (snapshot !== null && forwardEvent) { 103307 forwardEvent(new ActivationStart(snapshot)); 103308 } 103309 103310 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(true); 103311} 103312/** 103313 * This should fire off `ChildActivationStart` events for each route being activated at this 103314 * level. 103315 * In other words, if you're activating `a` and `b` below, `path` will contain the 103316 * `ActivatedRouteSnapshot`s for both and we will fire `ChildActivationStart` for both. Always 103317 * return 103318 * `true` so checks continue to run. 103319 */ 103320 103321 103322function fireChildActivationStart(snapshot, forwardEvent) { 103323 if (snapshot !== null && forwardEvent) { 103324 forwardEvent(new ChildActivationStart(snapshot)); 103325 } 103326 103327 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(true); 103328} 103329 103330function runCanActivate(futureRSS, futureARS, injector) { 103331 const canActivate = futureARS.routeConfig ? futureARS.routeConfig.canActivate : null; 103332 if (!canActivate || canActivate.length === 0) return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(true); 103333 const canActivateObservables = canActivate.map(canActivate => { 103334 return (0,rxjs__WEBPACK_IMPORTED_MODULE_15__.defer)(() => { 103335 const closestInjector = getClosestRouteInjector(futureARS) ?? injector; 103336 const guard = getTokenOrFunctionIdentity(canActivate, closestInjector); 103337 const guardVal = isCanActivate(guard) ? guard.canActivate(futureARS, futureRSS) : closestInjector.runInContext(() => guard(futureARS, futureRSS)); 103338 return wrapIntoObservable(guardVal).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)()); 103339 }); 103340 }); 103341 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(canActivateObservables).pipe(prioritizedGuardValue()); 103342} 103343 103344function runCanActivateChild(futureRSS, path, injector) { 103345 const futureARS = path[path.length - 1]; 103346 const canActivateChildGuards = path.slice(0, path.length - 1).reverse().map(p => getCanActivateChild(p)).filter(_ => _ !== null); 103347 const canActivateChildGuardsMapped = canActivateChildGuards.map(d => { 103348 return (0,rxjs__WEBPACK_IMPORTED_MODULE_15__.defer)(() => { 103349 const guardsMapped = d.guards.map(canActivateChild => { 103350 const closestInjector = getClosestRouteInjector(d.node) ?? injector; 103351 const guard = getTokenOrFunctionIdentity(canActivateChild, closestInjector); 103352 const guardVal = isCanActivateChild(guard) ? guard.canActivateChild(futureARS, futureRSS) : closestInjector.runInContext(() => guard(futureARS, futureRSS)); 103353 return wrapIntoObservable(guardVal).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)()); 103354 }); 103355 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(guardsMapped).pipe(prioritizedGuardValue()); 103356 }); 103357 }); 103358 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(canActivateChildGuardsMapped).pipe(prioritizedGuardValue()); 103359} 103360 103361function runCanDeactivate(component, currARS, currRSS, futureRSS, injector) { 103362 const canDeactivate = currARS && currARS.routeConfig ? currARS.routeConfig.canDeactivate : null; 103363 if (!canDeactivate || canDeactivate.length === 0) return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(true); 103364 const canDeactivateObservables = canDeactivate.map(c => { 103365 const closestInjector = getClosestRouteInjector(currARS) ?? injector; 103366 const guard = getTokenOrFunctionIdentity(c, closestInjector); 103367 const guardVal = isCanDeactivate(guard) ? guard.canDeactivate(component, currARS, currRSS, futureRSS) : closestInjector.runInContext(() => guard(component, currARS, currRSS, futureRSS)); 103368 return wrapIntoObservable(guardVal).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)()); 103369 }); 103370 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(canDeactivateObservables).pipe(prioritizedGuardValue()); 103371} 103372 103373function runCanLoadGuards(injector, route, segments, urlSerializer) { 103374 const canLoad = route.canLoad; 103375 103376 if (canLoad === undefined || canLoad.length === 0) { 103377 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(true); 103378 } 103379 103380 const canLoadObservables = canLoad.map(injectionToken => { 103381 const guard = getTokenOrFunctionIdentity(injectionToken, injector); 103382 const guardVal = isCanLoad(guard) ? guard.canLoad(route, segments) : injector.runInContext(() => guard(route, segments)); 103383 return wrapIntoObservable(guardVal); 103384 }); 103385 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(canLoadObservables).pipe(prioritizedGuardValue(), redirectIfUrlTree(urlSerializer)); 103386} 103387 103388function redirectIfUrlTree(urlSerializer) { 103389 return (0,rxjs__WEBPACK_IMPORTED_MODULE_16__.pipe)((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(result => { 103390 if (!isUrlTree(result)) return; 103391 throw redirectingNavigationError(urlSerializer, result); 103392 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(result => result === true)); 103393} 103394 103395function runCanMatchGuards(injector, route, segments, urlSerializer) { 103396 const canMatch = route.canMatch;
103397 if (!canMatch || canMatch.length === 0) return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(true); 103398 const canMatchObservables = canMatch.map(injectionToken => { 103399 const guard = getTokenOrFunctionIdentity(injectionToken, injector); 103400 const guardVal = isCanMatch(guard) ? guard.canMatch(route, segments) : injector.runInContext(() => guard(route, segments)); 103401 return wrapIntoObservable(guardVal); 103402 }); 103403 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(canMatchObservables).pipe(prioritizedGuardValue(), redirectIfUrlTree(urlSerializer)); 103404} 103405/** 103406 * @license 103407 * Copyright Google LLC All Rights Reserved. 103408 * 103409 * Use of this source code is governed by an MIT-style license that can be 103410 * found in the LICENSE file at https://angular.io/license 103411 */ 103412 103413 103414const noMatch$1 = { 103415 matched: false, 103416 consumedSegments: [], 103417 remainingSegments: [], 103418 parameters: {}, 103419 positionalParamSegments: {} 103420}; 103421 103422function matchWithChecks(segmentGroup, route, segments, injector, urlSerializer) { 103423 const result = match(segmentGroup, route, segments); 103424 103425 if (!result.matched) { 103426 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(result); 103427 }
103427 // Only create the Route's `EnvironmentInjector` if it matches the attempted 103428 // navigation 103429 103430 103431 injector = getOrCreateRouteInjectorIfNeeded(route, injector); 103432 return runCanMatchGuards(injector, route, segments, urlSerializer).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(v => v === true ? result : { ...noMatch$1 103433 })); 103434} 103435 103436function match(segmentGroup, route, segments) { 103437 if (route.path === '') { 103438 if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || segments.length > 0)) { 103439 return { ...noMatch$1 103440 }; 103441 } 103442 103443 return { 103444 matched: true, 103445 consumedSegments: [], 103446 remainingSegments: segments, 103447 parameters: {}, 103448 positionalParamSegments: {} 103449 }; 103450 } 103451 103452 const matcher = route.matcher || defaultUrlMatcher; 103453 const res = matcher(segments, segmentGroup, route); 103454 if (!res) return { ...noMatch$1 103455 }; 103456 const posParams = {}; 103457 forEach(res.posParams, (v, k) => { 103458 posParams[k] = v.path; 103459 }); 103460 const parameters = res.consumed.length > 0 ? { ...posParams, 103461 ...res.consumed[res.consumed.length - 1].parameters 103462 } : posParams; 103463 return { 103464 matched: true, 103465 consumedSegments: res.consumed, 103466 remainingSegments: segments.slice(res.consumed.length), 103467 // TODO(atscott): investigate combining parameters and positionalParamSegments 103468 parameters, 103469 positionalParamSegments: res.posParams ?? {} 103470 }; 103471} 103472 103473function split(segmentGroup, consumedSegments, slicedSegments, config, relativeLinkResolution = 'corrected') { 103474 if (slicedSegments.length > 0 && containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, config)) { 103475 const s = new UrlSegmentGroup(consumedSegments, createChildrenForEmptyPaths(segmentGroup, consumedSegments, config, new UrlSegmentGroup(slicedSegments, segmentGroup.children))); 103476 s._sourceSegment = segmentGroup; 103477 s._segmentIndexShift = consumedSegments.length; 103478 return { 103479 segmentGroup: s, 103480 slicedSegments: [] 103481 }; 103482 } 103483 103484 if (slicedSegments.length === 0 && containsEmptyPathMatches(segmentGroup, slicedSegments, config)) { 103485 const s = new UrlSegmentGroup(segmentGroup.segments, addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, config, segmentGroup.children, relativeLinkResolution)); 103486 s._sourceSegment = segmentGroup; 103487 s._segmentIndexShift = consumedSegments.length; 103488 return { 103489 segmentGroup: s, 103490 slicedSegments 103491 }; 103492 } 103493 103494 const s = new UrlSegmentGroup(segmentGroup.segments, segmentGroup.children); 103495 s._sourceSegment = segmentGroup; 103496 s._segmentIndexShift = consumedSegments.length; 103497 return { 103498 segmentGroup: s, 103499 slicedSegments 103500 }; 103501} 103502 103503function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, routes, children, relativeLinkResolution) { 103504 const res = {}; 103505 103506 for (const r of routes) { 103507 if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) { 103508 const s = new UrlSegmentGroup([], {}); 103509 s._sourceSegment = segmentGroup; 103510 103511 if (relativeLinkResolution === 'legacy') { 103512 s._segmentIndexShift = segmentGroup.segments.length; 103513 103514 if (typeof ngDevMode === 'undefined' || !!ngDevMode) { 103515 s._segmentIndexShiftCorrected = consumedSegments.length; 103516 } 103517 } else { 103518 s._segmentIndexShift = consumedSegments.length; 103519 } 103520 103521 res[getOutlet(r)] = s; 103522 } 103523 } 103524 103525 return { ...children, 103526 ...res 103527 }; 103528} 103529 103530function createChildrenForEmptyPaths(segmentGroup, consumedSegments, routes, primarySegment) { 103531 const res = {}; 103532 res[PRIMARY_OUTLET] = primarySegment; 103533 primarySegment._sourceSegment = segmentGroup; 103534 primarySegment._segmentIndexShift = consumedSegments.length; 103535 103536 for (const r of routes) { 103537 if (r.path === '' && getOutlet(r) !== PRIMARY_OUTLET) { 103538 const s = new UrlSegmentGroup([], {}); 103539 s._sourceSegment = segmentGroup; 103540 s._segmentIndexShift = consumedSegments.length; 103541 res[getOutlet(r)] = s; 103542 } 103543 } 103544 103545 return res; 103546} 103547 103548function containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, routes) { 103549 return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r) && getOutlet(r) !== PRIMARY_OUTLET); 103550} 103551 103552function containsEmptyPathMatches(segmentGroup, slicedSegments, routes) { 103553 return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r)); 103554} 103555 103556function emptyPathMatch(segmentGroup, slicedSegments, r) { 103557 if ((segmentGroup.hasChildren() || slicedSegments.length > 0) && r.pathMatch === 'full') { 103558 return false;
103559 } 103560 103561 return r.path === ''; 103562} 103563/** 103564 * Determines if `route` is a path match for the `rawSegment`, `segments`, and `outlet` without 103565 * verifying that its children are a full match for the remainder of the `rawSegment` children as 103566 * well. 103567 */ 103568 103569 103570function isImmediateMatch(route, rawSegment, segments, outlet) { 103571 // We allow matches to empty paths when the outlets differ so we can match a url like `/(b:b)` to 103572 // a config like 103573 // * `{path: '', children: [{path: 'b', outlet: 'b'}]}` 103574 // or even 103575 // * `{path: '', outlet: 'a', children: [{path: 'b', outlet: 'b'}]` 103576 // 103577 // The exception here is when the segment outlet is for the primary outlet. This would 103578 // result in a match inside the named outlet because all children there are written as primary 103579 // outlets. So we need to prevent child named outlet matches in a url like `/b` in a config like 103580 // * `{path: '', outlet: 'x' children: [{path: 'b'}]}` 103581 // This should only match if the url is `/(x:b)`. 103582 if (getOutlet(route) !== outlet && (outlet === PRIMARY_OUTLET || !emptyPathMatch(rawSegment, segments, route))) { 103583 return false; 103584 } 103585 103586 if (route.path === '**') { 103587 return true; 103588 } 103589 103590 return match(rawSegment, route, segments).matched; 103591} 103592 103593function noLeftoversInUrl(segmentGroup, segments, outlet) { 103594 return segments.length === 0 && !segmentGroup.children[outlet]; 103595} 103596/** 103597 * @license 103598 * Copyright Google LLC All Rights Reserved. 103599 * 103600 * Use of this source code is governed by an MIT-style license that can be 103601 * found in the LICENSE file at https://angular.io/license 103602 */ 103603 103604 103605const NG_DEV_MODE$6 = typeof ngDevMode === 'undefined' || ngDevMode; 103606 103607class NoMatch$1 { 103608 constructor(segmentGroup) { 103609 this.segmentGroup = segmentGroup || null; 103610 } 103611 103612} 103613 103614class AbsoluteRedirect { 103615 constructor(urlTree) { 103616 this.urlTree = urlTree; 103617 } 103618 103619} 103620 103621function noMatch(segmentGroup) { 103622 return (0,rxjs__WEBPACK_IMPORTED_MODULE_18__.throwError)(new NoMatch$1(segmentGroup)); 103623} 103624 103625function absoluteRedirect(newTree) { 103626 return (0,rxjs__WEBPACK_IMPORTED_MODULE_18__.throwError)(new AbsoluteRedirect(newTree)); 103627} 103628 103629function namedOutletsRedirect(redirectTo) { 103630 return (0,rxjs__WEBPACK_IMPORTED_MODULE_18__.throwError)(new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4000 103631 /* RuntimeErrorCode.NAMED_OUTLET_REDIRECT */ 103632 , NG_DEV_MODE$6 && `Only absolute redirects can have named outlets. redirectTo: '${redirectTo}'`)); 103633} 103634 103635function canLoadFails(route) { 103636 return (0,rxjs__WEBPACK_IMPORTED_MODULE_18__.throwError)(navigationCancelingError(NG_DEV_MODE$6 && `Cannot load children because the guard of the route "path: '${route.path}'" returned false`, 3 103637 /* NavigationCancellationCode.GuardRejected */ 103638 )); 103639} 103640/** 103641 * Returns the `UrlTree` with the redirection applied. 103642 * 103643 * Lazy modules are loaded along the way. 103644 */ 103645 103646 103647function applyRedirects$1(injector, configLoader, urlSerializer, urlTree, config) { 103648 return new ApplyRedirects(injector, configLoader, urlSerializer, urlTree, config).apply(); 103649} 103650 103651class ApplyRedirects { 103652 constructor(injector, configLoader, urlSerializer, urlTree, config) { 103653 this.injector = injector; 103654 this.configLoader = configLoader; 103655 this.urlSerializer = urlSerializer; 103656 this.urlTree = urlTree; 103657 this.config = config; 103658 this.allowRedirects = true; 103659 } 103660 103661 apply() { 103662 const splitGroup = split(this.urlTree.root, [], [], this.config).segmentGroup; // TODO(atscott): creating a new segment removes the _sourceSegment _segmentIndexShift, which is 103663 // only necessary to prevent failures in tests which assert exact object matches. The `split` is 103664 // now shared between `applyRedirects` and `recognize` but only the `recognize` step needs these 103665 // properties. Before the implementations were merged, the `applyRedirects` would not assign 103666 // them. We should be able to remove this logic as a "breaking change" but should do some more 103667 // investigation into the failures first. 103668 103669 const rootSegmentGroup = new UrlSegmentGroup(splitGroup.segments, splitGroup.children); 103670 const expanded$ = this.expandSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET); 103671 const urlTrees$ = expanded$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(rootSegmentGroup => { 103672 return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), this.urlTree.queryParams, this.urlTree.fragment); 103673 })); 103674 return urlTrees$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)(e => { 103675 if (e instanceof AbsoluteRedirect) { 103676 // After an absolute redirect we do not apply any more redirects! 103677 // If this implementation changes, update the documentation note in `redirectTo`. 103678 this.allowRedirects = false; // we need to run matching, so we can fetch all lazy-loaded modules 103679 103680 return this.match(e.urlTree); 103681 } 103682 103683 if (e instanceof NoMatch$1) { 103684 throw this.noMatchError(e); 103685 } 103686 103687 throw e; 103688 })); 103689 } 103690 103691 match(tree) { 103692 const expanded$ = this.expandSegmentGroup(this.injector, this.config, tree.root, PRIMARY_OUTLET); 103693 const mapped$ = expanded$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(rootSegmentGroup => { 103694 return this.createUrlTree(squashSegmentGroup(rootSegmentGroup), tree.queryParams, tree.fragment); 103695 })); 103696 return mapped$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)(e => { 103697 if (e instanceof NoMatch$1) { 103698 throw this.noMatchError(e); 103699 } 103700 103701 throw e; 103702 })); 103703 } 103704 103705 noMatchError(e) { 103706 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4002 103707 /* RuntimeErrorCode.NO_MATCH */ 103708 , NG_DEV_MODE$6 && `Cannot match any routes. URL Segment: '${e.segmentGroup}'`); 103709 } 103710 103711 createUrlTree(rootCandidate, queryParams, fragment) { 103712 const root = createRoot(rootCandidate); 103713 return new UrlTree(root, queryParams, fragment); 103714 } 103715
103716 expandSegmentGroup(injector, routes, segmentGroup, outlet) { 103717 if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) { 103718 return this.expandChildren(injector, routes, segmentGroup).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(children => new UrlSegmentGroup([], children))); 103719 } 103720 103721 return this.expandSegment(injector, segmentGroup, routes, segmentGroup.segments, outlet, true); 103722 } // Recursively expand segment groups for all the child outlets 103723 103724 103725 expandChildren(injector, routes, segmentGroup) { 103726 // Expand outlets one at a time, starting with the primary outlet. We need to do it this way 103727 // because an absolute redirect from the primary outlet takes precedence. 103728 const childOutlets = []; 103729 103730 for (const child of Object.keys(segmentGroup.children)) { 103731 if (child === 'primary') { 103732 childOutlets.unshift(child); 103733 } else { 103734 childOutlets.push(child); 103735 } 103736 } 103737 103738 return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(childOutlets).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.concatMap)(childOutlet => { 103739 const child = segmentGroup.children[childOutlet]; // Sort the routes so routes with outlets that match the segment appear 103740 // first, followed by routes for other outlets, which might match if they have an 103741 // empty path. 103742 103743 const sortedRoutes = sortByMatchingOutlets(routes, childOutlet); 103744 return this.expandSegmentGroup(injector, sortedRoutes, child, childOutlet).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(s => ({ 103745 segment: s, 103746 outlet: childOutlet 103747 }))); 103748 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_20__.scan)((children, expandedChild) => { 103749 children[expandedChild.outlet] = expandedChild.segment; 103750 return children; 103751 }, {}), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_21__.last)()); 103752 } 103753 103754 expandSegment(injector, segmentGroup, routes, segments, outlet, allowRedirects) { 103755 return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(routes).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.concatMap)(r => { 103756 const expanded$ = this.expandSegmentAgainstRoute(injector, segmentGroup, routes, r, segments, outlet, allowRedirects); 103757 return expanded$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)(e => { 103758 if (e instanceof NoMatch$1) { 103759 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null); 103760 } 103761 103762 throw e; 103763 })); 103764 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)(s => !!s), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)((e, _) => { 103765 if (isEmptyError(e)) { 103766 if (noLeftoversInUrl(segmentGroup, segments, outlet)) { 103767 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(new UrlSegmentGroup([], {})); 103768 } 103769 103770 return noMatch(segmentGroup); 103771 } 103772 103773 throw e; 103774 })); 103775 } 103776 103777 expandSegmentAgainstRoute(injector, segmentGroup, routes, route, paths, outlet, allowRedirects) { 103778 if (!isImmediateMatch(route, segmentGroup, paths, outlet)) { 103779 return noMatch(segmentGroup); 103780 } 103781 103782 if (route.redirectTo === undefined) { 103783 return this.matchSegmentAgainstRoute(injector, segmentGroup, route, paths, outlet); 103784 } 103785 103786 if (allowRedirects && this.allowRedirects) { 103787 return this.expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, paths, outlet); 103788 } 103789 103790 return noMatch(segmentGroup); 103791 } 103792 103793 expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) { 103794 if (route.path === '**') { 103795 return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet); 103796 } 103797 103798 return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet); 103799 } 103800 103801 expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) { 103802 const newTree = this.applyRedirectCommands([], route.redirectTo, {}); 103803 103804 if (route.redirectTo.startsWith('/')) { 103805 return absoluteRedirect(newTree); 103806 } 103807 103808 return this.lineralizeSegments(route, newTree).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(newSegments => { 103809 const group = new UrlSegmentGroup(newSegments, {}); 103810 return this.expandSegment(injector, group, routes, newSegments, outlet, false); 103811 })); 103812 } 103813
103814 expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) { 103815 const { 103816 matched, 103817 consumedSegments, 103818 remainingSegments, 103819 positionalParamSegments 103820 } = match(segmentGroup, route, segments); 103821 if (!matched) return noMatch(segmentGroup); 103822 const newTree = this.applyRedirectCommands(consumedSegments, route.redirectTo, positionalParamSegments); 103823 103824 if (route.redirectTo.startsWith('/')) { 103825 return absoluteRedirect(newTree); 103826 } 103827 103828 return this.lineralizeSegments(route, newTree).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(newSegments => { 103829 return this.expandSegment(injector, segmentGroup, routes, newSegments.concat(remainingSegments), outlet, false); 103830 })); 103831 } 103832 103833 matchSegmentAgainstRoute(injector, rawSegmentGroup, route, segments, outlet) { 103834 if (route.path === '**') { 103835 // Only create the Route's `EnvironmentInjector` if it matches the attempted navigation 103836 injector = getOrCreateRouteInjectorIfNeeded(route, injector); 103837 103838 if (route.loadChildren) { 103839 const loaded$ = route._loadedRoutes ? (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({ 103840 routes: route._loadedRoutes, 103841 injector: route._loadedInjector 103842 }) : this.configLoader.loadChildren(injector, route); 103843 return loaded$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(cfg => { 103844 route._loadedRoutes = cfg.routes; 103845 route._loadedInjector = cfg.injector; 103846 return new UrlSegmentGroup(segments, {}); 103847 })); 103848 } 103849 103850 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(new UrlSegmentGroup(segments, {})); 103851 } 103852 103853 return matchWithChecks(rawSegmentGroup, route, segments, injector, this.urlSerializer).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(({ 103854 matched, 103855 consumedSegments, 103856 remainingSegments 103857 }) => { 103858 if (!matched) return noMatch(rawSegmentGroup); // If the route has an injector created from providers, we should start using that. 103859 103860 injector = route._injector ?? injector; 103861 const childConfig$ = this.getChildConfig(injector, route, segments); 103862 return childConfig$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(routerConfig => { 103863 const childInjector = routerConfig.injector ?? injector; 103864 const childConfig = routerConfig.routes; 103865 const { 103866 segmentGroup: splitSegmentGroup, 103867 slicedSegments 103868 } = split(rawSegmentGroup, consumedSegments, remainingSegments, childConfig); // See comment on the other call to `split` about why this is necessary. 103869 103870 const segmentGroup = new UrlSegmentGroup(splitSegmentGroup.segments, splitSegmentGroup.children); 103871 103872 if (slicedSegments.length === 0 && segmentGroup.hasChildren()) { 103873 const expanded$ = this.expandChildren(childInjector, childConfig, segmentGroup); 103874 return expanded$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(children => new UrlSegmentGroup(consumedSegments, children))); 103875 } 103876 103877 if (childConfig.length === 0 && slicedSegments.length === 0) { 103878 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(new UrlSegmentGroup(consumedSegments, {})); 103879 } 103880 103881 const matchedOnOutlet = getOutlet(route) === outlet; 103882 const expanded$ = this.expandSegment(childInjector, segmentGroup, childConfig, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true); 103883 return expanded$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(cs => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children))); 103884 })); 103885 })); 103886 } 103887 103888 getChildConfig(injector, route, segments) { 103889 if (route.children) { 103890 // The children belong to the same module 103891 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({ 103892 routes: route.children, 103893 injector 103894 }); 103895 } 103896 103897 if (route.loadChildren) { 103898 // lazy children belong to the loaded module 103899 if (route._loadedRoutes !== undefined) { 103900 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({ 103901 routes: route._loadedRoutes, 103902 injector: route._loadedInjector 103903 }); 103904 } 103905 103906 return runCanLoadGuards(injector, route, segments, this.urlSerializer).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(shouldLoadResult => { 103907 if (shouldLoadResult) { 103908 return this.configLoader.loadChildren(injector, route).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(cfg => { 103909 route._loadedRoutes = cfg.routes; 103910 route._loadedInjector = cfg.injector; 103911 })); 103912 } 103913 103914 return canLoadFails(route); 103915 })); 103916 } 103917 103918 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({ 103919 routes: [], 103920 injector 103921 }); 103922 } 103923 103924 lineralizeSegments(route, urlTree) { 103925 let res = [];
103926 let c = urlTree.root; 103927 103928 while (true) { 103929 res = res.concat(c.segments); 103930 103931 if (c.numberOfChildren === 0) { 103932 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(res); 103933 } 103934 103935 if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) { 103936 return namedOutletsRedirect(route.redirectTo); 103937 } 103938 103939 c = c.children[PRIMARY_OUTLET]; 103940 } 103941 } 103942 103943 applyRedirectCommands(segments, redirectTo, posParams) { 103944 return this.applyRedirectCreateUrlTree(redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams); 103945 } 103946 103947 applyRedirectCreateUrlTree(redirectTo, urlTree, segments, posParams) { 103948 const newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams); 103949 return new UrlTree(newRoot, this.createQueryParams(urlTree.queryParams, this.urlTree.queryParams), urlTree.fragment); 103950 } 103951 103952 createQueryParams(redirectToParams, actualParams) { 103953 const res = {}; 103954 forEach(redirectToParams, (v, k) => { 103955 const copySourceValue = typeof v === 'string' && v.startsWith(':'); 103956 103957 if (copySourceValue) { 103958 const sourceName = v.substring(1); 103959 res[k] = actualParams[sourceName]; 103960 } else { 103961 res[k] = v; 103962 } 103963 }); 103964 return res; 103965 } 103966 103967 createSegmentGroup(redirectTo, group, segments, posParams) { 103968 const updatedSegments = this.createSegments(redirectTo, group.segments, segments, posParams); 103969 let children = {}; 103970 forEach(group.children, (child, name) => { 103971 children[name] = this.createSegmentGroup(redirectTo, child, segments, posParams); 103972 }); 103973 return new UrlSegmentGroup(updatedSegments, children); 103974 } 103975 103976 createSegments(redirectTo, redirectToSegments, actualSegments, posParams) { 103977 return redirectToSegments.map(s => s.path.startsWith(':') ? this.findPosParam(redirectTo, s, posParams) : this.findOrReturn(s, actualSegments)); 103978 } 103979 103980 findPosParam(redirectTo, redirectToUrlSegment, posParams) { 103981 const pos = posParams[redirectToUrlSegment.path.substring(1)]; 103982 if (!pos) throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4001 103983 /* RuntimeErrorCode.MISSING_REDIRECT */ 103984 , NG_DEV_MODE$6 && `Cannot redirect to '${redirectTo}'. Cannot find '${redirectToUrlSegment.path}'.`); 103985 return pos; 103986 } 103987 103988 findOrReturn(redirectToUrlSegment, actualSegments) { 103989 let idx = 0; 103990 103991 for (const s of actualSegments) { 103992 if (s.path === redirectToUrlSegment.path) { 103993 actualSegments.splice(idx); 103994 return s; 103995 } 103996 103997 idx++; 103998 } 103999 104000 return redirectToUrlSegment; 104001 } 104002 104003} 104004/** 104005 * @license 104006 * Copyright Google LLC All Rights Reserved. 104007 * 104008 * Use of this source code is governed by an MIT-style license that can be 104009 * found in the LICENSE file at https://angular.io/license 104010 */ 104011 104012 104013function applyRedirects(environmentInjector, configLoader, urlSerializer, config) { 104014 return (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(t => applyRedirects$1(environmentInjector, configLoader, urlSerializer, t.extractedUrl, config).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(urlAfterRedirects => ({ ...t, 104015 urlAfterRedirects 104016 })))); 104017} 104018/** 104019 * @license 104020 * Copyright Google LLC All Rights Reserved. 104021 * 104022 * Use of this source code is governed by an MIT-style license that can be 104023 * found in the LICENSE file at https://angular.io/license 104024 */ 104025 104026 104027const NG_DEV_MODE$5 = typeof ngDevMode === 'undefined' || !!ngDevMode; 104028 104029class NoMatch {} 104030 104031function newObservableError(e) { 104032 // TODO(atscott): This pattern is used throughout the router code and can be `throwError` instead. 104033 return new rxjs__WEBPACK_IMPORTED_MODULE_22__.Observable(obs => obs.error(e)); 104034} 104035 104036function recognize$1(injector, rootComponentType, config, urlTree, url, urlSerializer, paramsInheritanceStrategy = 'emptyOnly', relativeLinkResolution = 'legacy') { 104037 return new Recognizer(injector, rootComponentType, config, urlTree, url, paramsInheritanceStrategy, relativeLinkResolution, urlSerializer).recognize().pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(result => { 104038 if (result === null) { 104039 return newObservableError(new NoMatch()); 104040 } else { 104041 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(result); 104042 } 104043 })); 104044} 104045 104046class Recognizer { 104047 constructor(injector, rootComponentType, config, urlTree, url, paramsInheritanceStrategy, relativeLinkResolution, urlSerializer) { 104048 this.injector = injector; 104049 this.rootComponentType = rootComponentType; 104050 this.config = config; 104051 this.urlTree = urlTree; 104052 this.url = url; 104053 this.paramsInheritanceStrategy = paramsInheritanceStrategy; 104054 this.relativeLinkResolution = relativeLinkResolution; 104055 this.urlSerializer = urlSerializer; 104056 } 104057 104058 recognize() { 104059 const rootSegmentGroup = split(this.urlTree.root, [], [], this.config.filter(c => c.redirectTo === undefined), this.relativeLinkResolution).segmentGroup; 104060 return this.processSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(children => { 104061 if (children === null) { 104062 return null; 104063 } // Use Object.freeze to prevent readers of the Router state from modifying it outside of a 104064 // navigation, resulting in the router being out of sync with the browser. 104065 104066 104067 const root = new ActivatedRouteSnapshot([], Object.freeze({}), Object.freeze({ ...this.urlTree.queryParams 104068 }), this.urlTree.fragment, {}, PRIMARY_OUTLET, this.rootComponentType, null, this.urlTree.root, -1, {}); 104069 const rootNode = new TreeNode(root, children); 104070 const routeState = new RouterStateSnapshot(this.url, rootNode); 104071 this.inheritParamsAndData(routeState._root); 104072 return routeState; 104073 })); 104074 } 104075 104076 inheritParamsAndData(routeNode) { 104077 const route = routeNode.value; 104078 const i = inheritedParamsDataResolve(route, this.paramsInheritanceStrategy); 104079 route.params = Object.freeze(i.params); 104080 route.data = Object.freeze(i.data);
104081 routeNode.children.forEach(n => this.inheritParamsAndData(n)); 104082 } 104083 104084 processSegmentGroup(injector, config, segmentGroup, outlet) { 104085 if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) { 104086 return this.processChildren(injector, config, segmentGroup); 104087 } 104088 104089 return this.processSegment(injector, config, segmentGroup, segmentGroup.segments, outlet); 104090 } 104091 /** 104092 * Matches every child outlet in the `segmentGroup` to a `Route` in the config. Returns `null` if 104093 * we cannot find a match for _any_ of the children. 104094 * 104095 * @param config - The `Routes` to match against 104096 * @param segmentGroup - The `UrlSegmentGroup` whose children need to be matched against the 104097 * config. 104098 */ 104099 104100 104101 processChildren(injector, config, segmentGroup) { 104102 return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(Object.keys(segmentGroup.children)).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.concatMap)(childOutlet => { 104103 const child = segmentGroup.children[childOutlet]; // Sort the config so that routes with outlets that match the one being activated 104104 // appear first, followed by routes for other outlets, which might match if they have 104105 // an empty path. 104106 104107 const sortedConfig = sortByMatchingOutlets(config, childOutlet); 104108 return this.processSegmentGroup(injector, sortedConfig, child, childOutlet); 104109 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_20__.scan)((children, outletChildren) => { 104110 if (!children || !outletChildren) return null; 104111 children.push(...outletChildren); 104112 return children; 104113 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_23__.takeWhile)(children => children !== null), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_24__.defaultIfEmpty)(null), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_21__.last)(), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(children => { 104114 if (children === null) return null; // Because we may have matched two outlets to the same empty path segment, we can have 104115 // multiple activated results for the same outlet. We should merge the children of 104116 // these results so the final return value is only one `TreeNode` per outlet. 104117 104118 const mergedChildren = mergeEmptyPathMatches(children); 104119 104120 if (NG_DEV_MODE$5) { 104121 // This should really never happen - we are only taking the first match for each 104122 // outlet and merge the empty path matches. 104123 checkOutletNameUniqueness(mergedChildren); 104124 } 104125 104126 sortActivatedRouteSnapshots(mergedChildren); 104127 return mergedChildren; 104128 })); 104129 } 104130 104131 processSegment(injector, routes, segmentGroup, segments, outlet) { 104132 return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(routes).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.concatMap)(r => { 104133 return this.processSegmentAgainstRoute(r._injector ?? injector, r, segmentGroup, segments, outlet); 104134 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)(x => !!x), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)(e => { 104135 if (isEmptyError(e)) { 104136 if (noLeftoversInUrl(segmentGroup, segments, outlet)) { 104137 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)([]); 104138 } 104139 104140 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null); 104141 } 104142 104143 throw e; 104144 })); 104145 } 104146 104147 processSegmentAgainstRoute(injector, route, rawSegment, segments, outlet) { 104148 if (route.redirectTo || !isImmediateMatch(route, rawSegment, segments, outlet)) return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null); 104149 let matchResult; 104150 104151 if (route.path === '**') { 104152 const params = segments.length > 0 ? last(segments).parameters : {}; 104153 const pathIndexShift = getPathIndexShift(rawSegment) + segments.length; 104154 const snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze({ ...this.urlTree.queryParams 104155 }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), // NG_DEV_MODE is used to prevent the getCorrectedPathIndexShift function from affecting 104156 // production bundle size. This value is intended only to surface a warning to users 104157 // depending on `relativeLinkResolution: 'legacy'` in dev mode. 104158 NG_DEV_MODE$5 ? getCorrectedPathIndexShift(rawSegment) + segments.length : pathIndexShift); 104159 matchResult = (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({ 104160 snapshot, 104161 consumedSegments: [], 104162 remainingSegments: [] 104163 }); 104164 } else { 104165 matchResult = matchWithChecks(rawSegment, route, segments, injector, this.urlSerializer).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(({ 104166 matched, 104167 consumedSegments, 104168 remainingSegments, 104169 parameters 104170 }) => { 104171 if (!matched) { 104172 return null; 104173 } 104174 104175 const pathIndexShift = getPathIndexShift(rawSegment) + consumedSegments.length; 104176 const snapshot = new ActivatedRouteSnapshot(consumedSegments, parameters, Ob
104176ject.freeze({ ...this.urlTree.queryParams 104177 }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getSourceSegmentGroup(rawSegment), pathIndexShift, getResolve(route), NG_DEV_MODE$5 ? getCorrectedPathIndexShift(rawSegment) + consumedSegments.length : pathIndexShift); 104178 return { 104179 snapshot, 104180 consumedSegments, 104181 remainingSegments 104182 }; 104183 })); 104184 } 104185 104186 return matchResult.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(result => { 104187 if (result === null) { 104188 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null); 104189 } 104190 104191 const { 104192 snapshot, 104193 consumedSegments, 104194 remainingSegments 104195 } = result; // If the route has an injector created from providers, we should start using that. 104196 104197 injector = route._injector ?? injector; 104198 const childInjector = route._loadedInjector ?? injector; 104199 const childConfig = getChildConfig(route); 104200 const { 104201 segmentGroup, 104202 slicedSegments 104203 } = split(rawSegment, consumedSegments, remainingSegments, // Filter out routes with redirectTo because we are trying to create activated route 104204 // snapshots and don't handle redirects here. That should have been done in 104205 // `applyRedirects`. 104206 childConfig.filter(c => c.redirectTo === undefined), this.relativeLinkResolution); 104207 104208 if (slicedSegments.length === 0 && segmentGroup.hasChildren()) { 104209 return this.processChildren(childInjector, childConfig, segmentGroup).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(children => { 104210 if (children === null) { 104211 return null; 104212 } 104213 104214 return [new TreeNode(snapshot, children)]; 104215 })); 104216 } 104217 104218 if (childConfig.length === 0 && slicedSegments.length === 0) { 104219 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)([new TreeNode(snapshot, [])]); 104220 } 104221 104222 const matchedOnOutlet = getOutlet(route) === outlet; // If we matched a config due to empty path match on a different outlet, we need to 104223 // continue passing the current outlet for the segment rather than switch to PRIMARY. 104224 // Note that we switch to primary when we have a match because outlet configs look like 104225 // this: {path: 'a', outlet: 'a', children: [ 104226 // {path: 'b', component: B}, 104227 // {path: 'c', component: C}, 104228 // ]} 104229 // Notice that the children of the named outlet are configured with the primary outlet 104230 104231 return this.processSegment(childInjector, childConfig, segmentGroup, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(children => { 104232 if (children === null) { 104233 return null; 104234 } 104235 104236 return [new TreeNode(snapshot, children)]; 104237 })); 104238 })); 104239 } 104240 104241} 104242 104243function sortActivatedRouteSnapshots(nodes) { 104244 nodes.sort((a, b) => { 104245 if (a.value.outlet === PRIMARY_OUTLET) return -1; 104246 if (b.value.outlet === PRIMARY_OUTLET) return 1; 104247 return a.value.outlet.localeCompare(b.value.outlet); 104248 }); 104249} 104250 104251function getChildConfig(route) { 104252 if (route.children) { 104253 return route.children; 104254 } 104255 104256 if (route.loadChildren) { 104257 return route._loadedRoutes; 104258 } 104259 104260 return []; 104261} 104262 104263function hasEmptyPathConfig(node) { 104264 const config = node.value.routeConfig; 104265 return config && config.path === '' && config.redirectTo === undefined; 104266} 104267/** 104268 * Finds `TreeNode`s with matching empty path route configs and merges them into `TreeNode` with 104269 * the children from each duplicate. This is necessary because different outlets can match a 104270 * single empty path route config and the results need to then be merged. 104271 */ 104272 104273 104274function mergeEmptyPathMatches(nodes) { 104275 const result = []; // The set of nodes which contain children that were merged from two duplicate empty path nodes. 104276 104277 const mergedNodes = new Set(); 104278 104279 for (const node of nodes) { 104280 if (!hasEmptyPathConfig(node)) { 104281 result.push(node); 104282 continue; 104283 } 104284 104285 const duplicateEmptyPathNode = result.find(resultNode => node.value.routeConfig === resultNode.value.routeConfig); 104286 104287 if (duplicateEmptyPathNode !== undefined) {
104288 duplicateEmptyPathNode.children.push(...node.children); 104289 mergedNodes.add(duplicateEmptyPathNode); 104290 } else { 104291 result.push(node); 104292 } 104293 } // For each node which has children from multiple sources, we need to recompute a new `TreeNode` 104294 // by also merging those children. This is necessary when there are multiple empty path configs 104295 // in a row. Put another way: whenever we combine children of two nodes, we need to also check 104296 // if any of those children can be combined into a single node as well. 104297 104298 104299 for (const mergedNode of mergedNodes) { 104300 const mergedChildren = mergeEmptyPathMatches(mergedNode.children); 104301 result.push(new TreeNode(mergedNode.value, mergedChildren)); 104302 } 104303 104304 return result.filter(n => !mergedNodes.has(n)); 104305} 104306 104307function checkOutletNameUniqueness(nodes) { 104308 const names = {}; 104309 nodes.forEach(n => { 104310 const routeWithSameOutletName = names[n.value.outlet]; 104311 104312 if (routeWithSameOutletName) { 104313 const p = routeWithSameOutletName.url.map(s => s.toString()).join('/'); 104314 const c = n.value.url.map(s => s.toString()).join('/'); 104315 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4006 104316 /* RuntimeErrorCode.TWO_SEGMENTS_WITH_SAME_OUTLET */ 104317 , NG_DEV_MODE$5 && `Two segments cannot have the same outlet name: '${p}' and '${c}'.`); 104318 } 104319 104320 names[n.value.outlet] = n.value; 104321 }); 104322} 104323 104324function getSourceSegmentGroup(segmentGroup) { 104325 let s = segmentGroup; 104326 104327 while (s._sourceSegment) { 104328 s = s._sourceSegment; 104329 } 104330 104331 return s; 104332} 104333 104334function getPathIndexShift(segmentGroup) { 104335 let s = segmentGroup; 104336 let res = s._segmentIndexShift ?? 0; 104337 104338 while (s._sourceSegment) { 104339 s = s._sourceSegment; 104340 res += s._segmentIndexShift ?? 0; 104341 } 104342 104343 return res - 1; 104344} 104345 104346function getCorrectedPathIndexShift(segmentGroup) { 104347 let s = segmentGroup; 104348 let res = s._segmentIndexShiftCorrected ?? s._segmentIndexShift ?? 0; 104349 104350 while (s._sourceSegment) { 104351 s = s._sourceSegment; 104352 res += s._segmentIndexShiftCorrected ?? s._segmentIndexShift ?? 0; 104353 } 104354 104355 return res - 1; 104356} 104357 104358function getData(route) { 104359 return route.data || {}; 104360} 104361 104362function getResolve(route) { 104363 return route.resolve || {}; 104364} 104365/** 104366 * @license 104367 * Copyright Google LLC All Rights Reserved. 104368 * 104369 * Use of this source code is governed by an MIT-style license that can be 104370 * found in the LICENSE file at https://angular.io/license 104371 */ 104372 104373 104374function recognize(injector, rootComponentType, config, serializer, paramsInheritanceStrategy, relativeLinkResolution) { 104375 return (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(t => recognize$1(injector, rootComponentType, config, t.urlAfterRedirects, serializer.serialize(t.urlAfterRedirects), serializer, paramsInheritanceStrategy, relativeLinkResolution).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(targetSnapshot => ({ ...t, 104376 targetSnapshot 104377 })))); 104378} 104379/** 104380 * @license 104381 * Copyright Google LLC All Rights Reserved. 104382 * 104383 * Use of this source code is governed by an MIT-style license that can be 104384 * found in the LICENSE file at https://angular.io/license 104385 */ 104386 104387 104388function resolveData(paramsInheritanceStrategy, injector) { 104389 return (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(t => { 104390 const { 104391 targetSnapshot, 104392 guards: { 104393 canActivateChecks 104394 } 104395 } = t; 104396 104397 if (!canActivateChecks.length) { 104398 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(t); 104399 } 104400 104401 let canActivateChecksResolved = 0; 104402 return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(canActivateChecks).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.concatMap)(check => runResolve(check.route, targetSnapshot, paramsInheritanceStrategy, injector)), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(() => canActivateChecksResolved++), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_25__.takeLast)(1), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(_ => canActivateChecksResolved === canActivateChecks.length ? (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(t) : rxjs__WEBPACK_IMPORTED_MODULE_26__.EMPTY)); 104403 }); 104404} 104405 104406function runResolve(futureARS, futureRSS, paramsInheritanceStrategy, injector) { 104407 const config = futureARS.routeConfig; 104408 const resolve = futureARS._resolve; 104409 104410 if (config?.title !== undefined && !hasStaticTitle(config)) { 104411 resolve[RouteTitleKey] = config.title; 104412 } 104413 104414 return resolveNode(resolve, futureARS, futureRSS, injector).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(resolvedData => { 104415 futureARS._resolvedData = resolvedData; 104416 futureARS.data = inheritedParamsDataResolve(futureARS, paramsInheritanceStrategy).resolve; 104417 104418 if (config && hasStaticTitle(config)) { 104419 futureARS.data[RouteTitleKey] = config.title; 104420 } 104421 104422 return null; 104423 })); 104424} 104425 104426function resolveNode(resolve, futureARS, futureRSS, injector) { 104427 const keys = getDataKeys(resolve); 104428 104429 if (keys.length === 0) { 104430 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({}); 104431 } 104432 104433 const data = {}; 104434 return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(keys).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(key => getResolver(resolve[key], futureARS, futureRSS, injector).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_12__.first)(), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(value => { 104435 data[key] = value; 104436 }))), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_25__.takeLast)(1), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_27__.mapTo)(data), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)(e => isEmptyError(e) ? rxjs__WEBPACK_IMPORTED_MODULE_26__.EMPTY : (0,rxjs__WEBPACK_IMPORTED_MODULE_18__.throwError)(e))); 104437} 104438 104439function getDataKeys(obj) { 104440 return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)]; 104441} 104442 104443function getResolver(injectionToken, futureARS, futureRSS, injector) { 104444 const closestInjector = getClosestRouteInjector(futureARS) ?? injector; 104445 const resolver = getTokenOrFunctionIdentity(injectionToken, closestInjector); 104446 const resolverValue = resolver.resolve ? resolver.resolve(futureARS, futureRSS) : closestInjector.runInContext(() => resolver(futureARS, futureRSS)); 104447 return wrapIntoObservable(resolverValue); 104448} 104449 104450function hasStaticTitle(config) { 104451 return typeof config.title === 'string' || config.title === null; 104452} 104453/** 104454 * @license 104455 * Copyright Google LLC All Rights Reserved. 104456 * 104457 * Use of this source code is governed by an MIT-style license that can be 104458 * found in the LICENSE file at https://angular.io/license 104459 */ 104460 104461/** 104462 * Perform a side effect through a switchMap for every emission on the source Observable, 104463 * but return an Observable that is identical to the source. It's essentially the same as 104464 * the `tap` operator, but if the side effectful `next` function returns an ObservableInput, 104465 * it will wait before continuing with the original value. 104466 */ 104467 104468 104469function switchTap(next) { 104470 return (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(v => { 104471 const nextResult = next(v); 104472 104473 if (nextResult) { 104474 return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(nextResult).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(() => v)); 104475 } 104476 104477 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(v); 104478 }); 104479} 104480/** 104481 * @license 104482 * Copyright Google LLC All Rights Reserved. 104483 * 104484 * Use of this source code is governed by an MIT-style license that can be 104485 * found in the LICENSE file at https://angular.io/license 104486 */ 104487 104488/** 104489 * Provides a strategy for setting the page title after a router navigation. 104490 * 104491 * The built-in implementation traverses the router state snapshot and finds the deepest primary 104492 * outlet with `title` property. Given the `Routes` below, navigating to 104493 * `/base/child(popup:aux)` would result in the document title being set to "child". 104494 * ``` 104495 * [ 104496 * {path: 'base', title: 'base', children: [ 104497 * {path: 'child', title: 'child'}, 104498 * ], 104499 * {path: 'aux', outlet: 'popup', title: 'popupTitle'} 104500 * ] 104501 * ``` 104502 * 104503 * This class can be used as a base class for custom title strategies. That is, you can create your 104504 * own class that extends the `TitleStrategy`. Note that in the above example, the `title` 104505 * from the named outlet is never used. However, a custom strategy might be implemented to 104506 * incorporate titles in named outlets. 104507 * 104508 * @publicApi 104509 * @see [Page title guide](guide/router#setting-the-page-title) 104510 */ 104511 104512 104513class TitleStrategy { 104514 /** 104515 * @returns The `title` of the deepest primary route. 104516 */ 104517 buildTitle(snapshot) { 104518 let pageTitle; 104519 let route = snapshot.root; 104520 104521 while (route !== undefined) { 104522 pageTitle = this.getResolvedTitleForRoute(route) ?? pageTitle; 104523 route = route.children.find(child => child.outlet === PRIMARY_OUTLET); 104524 } 104525 104526 return pageTitle; 104527 } 104528 /** 104529 * Given an `ActivatedRouteSnapshot`, returns the final value of the 104530 * `Route.title` property, which can either be a static string or a resolved value. 104531 */ 104532 104533 104534 getResolvedTitleForRoute(snapshot) { 104535 return snapshot.data[RouteTitleKey]; 104536 } 104537 104538} 104539 104540TitleStrategy.ɵfac = function TitleStrategy_Factory(t) { 104541 return new (t || TitleStrategy)(); 104542}; 104543 104544TitleStrategy.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 104545 token: TitleStrategy, 104546 factory: function () { 104547 return (() => (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(DefaultTitleStrategy))(); 104548 }, 104549 providedIn: 'root' 104550}); 104551 104552(function () { 104553 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](TitleStrategy, [{ 104554 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 104555 args: [{ 104556 providedIn: 'root', 104557 useFactory: () => (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(DefaultTitleStrategy) 104558 }] 104559 }], null, null); 104560})(); 104561/** 104562 * The default `TitleStrategy` used by the router that updates the title using the `Title` service. 104563 */ 104564 104565 104566class DefaultTitleStrategy extends TitleStrategy { 104567 constructor(title) { 104568 super(); 104569 this.title = title; 104570 } 104571 /** 104572 * Sets the title of the browser to the given value. 104573 * 104574 * @param title The `pageTitle` from the deepest primary route. 104575 */ 104576 104577 104578 updateTitle(snapshot) { 104579 const title = this.buildTitle(snapshot); 104580 104581 if (title !== undefined) { 104582 this.title.setTitle(title); 104583 } 104584 } 104585 104586} 104587 104588DefaultTitleStrategy.ɵfac = function DefaultTitleStrategy_Factory(t) { 104589 return new (t || DefaultTitleStrategy)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_platform_browser__WEBPACK_IMPORTED_MODULE_28__.Title)); 104590}; 104591 104592DefaultTitleStrategy.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 104593 token: DefaultTitleStrategy, 104594 factory: DefaultTitleStrategy.ɵfac, 104595 providedIn: 'root' 104596}); 104597 104598(function () { 104599 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](DefaultTitleStrategy, [{ 104600 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 104601 args: [{ 104602 providedIn: 'root' 104603 }] 104604 }], function () { 104605 return [{ 104606 type: _angular_platform_browser__WEBPACK_IMPORTED_MODULE_28__.Title 104607 }]; 104608 }, null); 104609})(); 104610/** 104611 * @license 104612 * Copyright Google LLC All Rights Reserved. 104613 * 104614 * Use of this source code is governed by an MIT-style license that can be 104615 * found in the LICENSE file at https://angular.io/license 104616 */ 104617 104618/** 104619 * Exists to aid internal migration off of the deprecated relativeLinkResolution option. 104620 */ 104621 104622 104623function assignRelativeLinkResolution(router) {} 104624/** 104625 * @license 104626 * Copyright Google LLC All Rights Reserved. 104627 * 104628 * Use of this source code is governed by an MIT-style license that can be 104629 * found in the LICENSE file at https://angular.io/license 104630 */ 104631 104632/** 104633 * @description 104634 * 104635 * Provides a way to customize when activated routes get reused. 104636 * 104637 * @publicApi 104638 */ 104639 104640 104641class RouteReuseStrategy {}
104642/** 104643 * @description 104644 * 104645 * This base route reuse strategy only reuses routes when the matched router configs are 104646 * identical. This prevents components from being destroyed and recreated 104647 * when just the route parameters, query parameters or fragment change 104648 * (that is, the existing component is _reused_). 104649 * 104650 * This strategy does not store any routes for later reuse. 104651 * 104652 * Angular uses this strategy by default. 104653 * 104654 * 104655 * It can be used as a base class for custom route reuse strategies, i.e. you can create your own 104656 * class that extends the `BaseRouteReuseStrategy` one. 104657 * @publicApi 104658 */ 104659 104660 104661class BaseRouteReuseStrategy { 104662 /** 104663 * Whether the given route should detach for later reuse. 104664 * Always returns false for `BaseRouteReuseStrategy`. 104665 * */ 104666 shouldDetach(route) { 104667 return false; 104668 } 104669 /** 104670 * A no-op; the route is never stored since this strategy never detaches routes for later re-use. 104671 */ 104672 104673 104674 store(route, detachedTree) {} 104675 /** Returns `false`, meaning the route (and its subtree) is never reattached */ 104676 104677 104678 shouldAttach(route) { 104679 return false; 104680 } 104681 /** Returns `null` because this strategy does not store routes for later re-use. */ 104682 104683 104684 retrieve(route) { 104685 return null; 104686 } 104687 /** 104688 * Determines if a route should be reused. 104689 * This strategy returns `true` when the future route config and current route config are 104690 * identical. 104691 */ 104692 104693 104694 shouldReuseRoute(future, curr) { 104695 return future.routeConfig === curr.routeConfig; 104696 } 104697 104698} 104699 104700class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {} 104701/** 104702 * @license 104703 * Copyright Google LLC All Rights Reserved. 104704 * 104705 * Use of this source code is governed by an MIT-style license that can be 104706 * found in the LICENSE file at https://angular.io/license 104707 */ 104708 104709 104710const NG_DEV_MODE$4 = typeof ngDevMode === 'undefined' || !!ngDevMode; 104711/** 104712 * A [DI token](guide/glossary/#di-token) for the router service. 104713 * 104714 * @publicApi 104715 */ 104716 104717const ROUTER_CONFIGURATION = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken(NG_DEV_MODE$4 ? 'router config' : '', { 104718 providedIn: 'root', 104719 factory: () => ({}) 104720}); 104721/** 104722 * @license 104723 * Copyright Google LLC All Rights Reserved. 104724 * 104725 * Use of this source code is governed by an MIT-style license that can be 104726 * found in the LICENSE file at https://angular.io/license 104727 */ 104728 104729const NG_DEV_MODE$3 = typeof ngDevMode === 'undefined' || !!ngDevMode; 104730/** 104731 * The [DI token](guide/glossary/#di-token) for a router configuration. 104732 * 104733 * `ROUTES` is a low level API for router configuration via depen
104733dency injection. 104734 * 104735 * We recommend that in almost all cases to use higher level APIs such as `RouterModule.forRoot()`, 104736 * `RouterModule.forChild()`, `provideRoutes`, or `Router.resetConfig()`. 104737 * 104738 * @publicApi 104739 */ 104740 104741const ROUTES = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('ROUTES'); 104742 104743class RouterConfigLoader { 104744 constructor(injector, compiler) { 104745 this.injector = injector; 104746 this.compiler = compiler; 104747 this.componentLoaders = new WeakMap(); 104748 this.childrenLoaders = new WeakMap(); 104749 } 104750 104751 loadComponent(route) { 104752 if (this.componentLoaders.get(route)) { 104753 return this.componentLoaders.get(route); 104754 } else if (route._loadedComponent) { 104755 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(route._loadedComponent); 104756 } 104757 104758 if (this.onLoadStartListener) { 104759 this.onLoadStartListener(route); 104760 } 104761 104762 const loadRunner = wrapIntoObservable(route.loadComponent()).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(component => { 104763 if (this.onLoadEndListener) { 104764 this.onLoadEndListener(route); 104765 } 104766 104767 NG_DEV_MODE$3 && assertStandalone(route.path ?? '', component); 104768 route._loadedComponent = component; 104769 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_29__.finalize)(() => { 104770 this.componentLoaders.delete(route); 104771 })); // Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much 104772 104773 const loader = new rxjs__WEBPACK_IMPORTED_MODULE_30__.ConnectableObservable(loadRunner, () => new rxjs__WEBPACK_IMPORTED_MODULE_31__.Subject()).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_32__.refCount)()); 104774 this.componentLoaders.set(route, loader); 104775 return loader; 104776 } 104777 104778 loadChildren(parentInjector, route) { 104779 if (this.childrenLoaders.get(route)) { 104780 return this.childrenLoaders.get(route); 104781 } else if (route._loadedRoutes) { 104782 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)({ 104783 routes: route._loadedRoutes, 104784 injector: route._loadedInjector 104785 }); 104786 } 104787 104788 if (this.onLoadStartListener) { 104789 this.onLoadStartListener(route); 104790 } 104791 104792 const moduleFactoryOrRoutes$ = this.loadModuleFactoryOrRoutes(route.loadChildren); 104793 const loadRunner = moduleFactoryOrRoutes$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(factoryOrRoutes => { 104794 if (this.onLoadEndListener) { 104795 this.onLoadEndListener(route); 104796 } // This injector comes from the `NgModuleRef` when lazy loading an `NgModule`. There is no 104797 // injector associated with lazy loading a `Route` array. 104798 104799 104800 let injector; 104801 let rawRoutes; 104802 let requireStandaloneComponents = false; 104803 104804 if (Array.isArray(factoryOrRoutes)) { 104805 rawRoutes = factoryOrRoutes; 104806 requireStandaloneComponents = true; 104807 } else { 104808 injector = factoryOrRoutes.create(parentInjector).injector; // When loading a module that doesn't provide `RouterModule.forChild()` preloader 104809 // will get stuck in an infinite loop. The child module's Injector will look to 104810 // its parent `Injector` when it doesn't find any ROUTES so it will return routes 104811 // for it's parent module instead. 104812 104813 rawRoutes = flatten(injector.get(ROUTES, [], _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectFlags.Self | _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectFlags.Optional)); 104814 } 104815 104816 const routes = rawRoutes.map(standardizeConfig); 104817 NG_DEV_MODE$3 && validateConfig(routes, route.path, requireStandaloneComponents); 104818 return { 104819 routes, 104820 injector 104821 }; 104822 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_29__.finalize)(() => { 104823 this.childrenLoaders.delete(route); 104824 })); // Use custom ConnectableObservable as share in runners pipe increasing the bundle size too much 104825 104826 const loader = new rxjs__WEBPACK_IMPORTED_MODULE_30__.ConnectableObservable(loadRunner, () => new rxjs__WEBPACK_IMPORTED_MODULE_31__.Subject()).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_32__.refCount)()); 104827 this.childrenLoaders.set(route, loader); 104828 return loader; 104829 } 104830 104831 loadModuleFactoryOrRoutes(loadChildren) { 104832 return wrapIntoObservable(loadChildren()).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(t => { 104833 if (t instanceof _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModuleFactory || Array.isArray(t)) { 104834 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(t); 104835 } else { 104836 return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(this.compiler.compileModuleAsync(t)); 104837 } 104838 })); 104839 } 104840 104841} 104842 104843RouterConfigLoader.ɵfac = function RouterConfigLoader_Factory(t) { 104844 return new (t || RouterConfigLoader)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Compiler)); 104845}; 104846 104847RouterConfigLoader.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 104848 token: RouterConfigLoader, 104849 factory: RouterConfigLoader.ɵfac, 104850 providedIn: 'root' 104851}); 104852 104853(function () { 104854 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterConfigLoader, [{ 104855 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 104856 args: [{ 104857 providedIn: 'root' 104858 }] 104859 }], function () { 104860 return [{ 104861 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector 104862 }, {
104863 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Compiler 104864 }]; 104865 }, null); 104866})(); 104867/** 104868 * @license 104869 * Copyright Google LLC All Rights Reserved. 104870 * 104871 * Use of this source code is governed by an MIT-style license that can be 104872 * found in the LICENSE file at https://angular.io/license 104873 */ 104874 104875/** 104876 * @description 104877 * 104878 * Provides a way to migrate AngularJS applications to Angular. 104879 * 104880 * @publicApi 104881 */ 104882 104883 104884class UrlHandlingStrategy {} 104885/** 104886 * @publicApi 104887 */ 104888 104889 104890class DefaultUrlHandlingStrategy { 104891 shouldProcessUrl(url) { 104892 return true; 104893 } 104894 104895 extract(url) { 104896 return url; 104897 } 104898 104899 merge(newUrlPart, wholeUrl) { 104900 return newUrlPart; 104901 } 104902 104903} 104904/** 104905 * @license 104906 * Copyright Google LLC All Rights Reserved. 104907 * 104908 * Use of this source code is governed by an MIT-style license that can be 104909 * found in the LICENSE file at https://angular.io/license 104910 */ 104911 104912 104913const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode; 104914 104915function defaultErrorHandler(error) { 104916 throw error; 104917} 104918 104919function defaultMalformedUriErrorHandler(error, urlSerializer, url) { 104920 return urlSerializer.parse('/'); 104921} 104922/** 104923 * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `true` 104924 * (exact = true). 104925 */ 104926 104927 104928const exactMatchOptions = { 104929 paths: 'exact', 104930 fragment: 'ignored', 104931 matrixParams: 'ignored', 104932 queryParams: 'exact' 104933}; 104934/** 104935 * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `false` 104936 * (exact = false). 104937 */ 104938 104939const subsetMatchOptions = { 104940 paths: 'subset', 104941 fragment: 'ignored', 104942 matrixParams: 'ignored', 104943 queryParams: 'subset' 104944}; 104945 104946function assignExtraOptionsToRouter(opts, router) { 104947 if (opts.errorHandler) { 104948 router.errorHandler = opts.errorHandler; 104949 } 104950 104951 if (opts.malformedUriErrorHandler) { 104952 router.malformedUriErrorHandler = opts.malformedUriErrorHandler; 104953 } 104954 104955 if (opts.onSameUrlNavigation) { 104956 router.onSameUrlNavigation = opts.onSameUrlNavigation; 104957 } 104958 104959 if (opts.paramsInheritanceStrategy) { 104960 router.paramsInheritanceStrategy = opts.paramsInheritanceStrategy; 104961 } 104962 104963 if (opts.relativeLinkResolution) { 104964 router.relativeLinkResolution = opts.relativeLinkResolution; 104965 } 104966 104967 if (opts.urlUpdateStrategy) { 104968 router.urlUpdateStrategy = opts.urlUpdateStrategy; 104969 } 104970 104971 if (opts.canceledNavigationResolution) { 104972 router.canceledNavigationResolution = opts.canceledNavigationResolution; 104973 } 104974} 104975 104976function setupRouter() { 104977 const urlSerializer = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(UrlSerializer); 104978 const contexts = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(ChildrenOutletContexts); 104979 const location = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_33__.Location); 104980 const injector = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector); 104981 const compiler = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.Compiler); 104982 const config = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(ROUTES, { 104983 optional: true 104984 }) ?? []; 104985 const opts = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(ROUTER_CONFIGURATION, { 104986 optional: true 104987 }) ?? {}; 104988 const defaultTitleStrategy = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(DefaultTitleStrategy); 104989 const titleStrategy = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(TitleStrategy, { 104990 optional: true 104991 }); 104992 const urlHandlingStrategy = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(UrlHandlingStrategy, { 104993 optional: true 104994 }); 104995 const routeReuseStrategy = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(RouteReuseStrategy, { 104996 optional: true 104997 }); 104998 const router = new Router(null, urlSerializer, contexts, location, injector, compiler, flatten(config)); 104999 105000 if (urlHandlingStrategy) { 105001 router.urlHandlingStrategy = urlHandlingStrategy; 105002 } 105003 105004 if (routeReuseStrategy) { 105005 router.routeReuseStrategy = routeReuseStrategy; 105006 } 105007 105008 router.titleStrategy = titleStrategy ?? defaultTitleStrategy; 105009 assignExtraOptionsToRouter(opts, router); 105010 assignRelativeLinkResolution(router); 105011 return router; 105012} 105013/** 105014 * @description 105015 * 105016 * A service that provides navigation among views and URL manipulation capabilities. 105017 * 105018 * @see `Route`. 105019 * @see [Routing and Navigation Guide](guide/router). 105020 * 105021 * @ngModule RouterModule 105022 * 105023 * @publicApi 105024 */ 105025 105026 105027class Router { 105028 /** 105029 * Creates the router service. 105030 */ 105031 // TODO: vsavkin make internal after the final is out. 105032 constructor(rootComponentType, urlSerializer, rootContexts, location, injector, compiler, config) { 105033 this.rootComponentType = rootComponentType; 105034 this.urlSerializer = urlSerializer; 105035 this.rootContexts = rootContexts; 105036 this.location = location; 105037 this.config = config; 105038 this.lastSuccessfulNavigation = null; 105039 this.currentNavigation = null; 105040 this.disposed = false;
105041 this.navigationId = 0; 105042 /** 105043 * The id of the currently active page in the router. 105044 * Updated to the transition's target id on a successful navigation. 105045 * 105046 * This is used to track what page the router last activated. When an attempted navigation fails, 105047 * the router can then use this to compute how to restore the state back to the previously active 105048 * page. 105049 */ 105050 105051 this.currentPageId = 0; 105052 this.isNgZoneEnabled = false; 105053 /** 105054 * An event stream for routing events in this NgModule. 105055 */ 105056 105057 this.events = new rxjs__WEBPACK_IMPORTED_MODULE_31__.Subject(); 105058 /** 105059 * A handler for navigation errors in this NgModule. 105060 */ 105061 105062 this.errorHandler = defaultErrorHandler; 105063 /** 105064 * A handler for errors thrown by `Router.parseUrl(url)` 105065 * when `url` contains an invalid character. 105066 * The most common case is a `%` sign 105067 * that's not encoded and is not part of a percent encoded sequence. 105068 */ 105069 105070 this.malformedUriErrorHandler = defaultMalformedUriErrorHandler; 105071 /** 105072 * True if at least one navigation event has occurred, 105073 * false otherwise. 105074 */ 105075 105076 this.navigated = false; 105077 this.lastSuccessfulId = -1; 105078 /** 105079 * Hook that enables you to pause navigation after the preactivation phase. 105080 * Used by `RouterModule`. 105081 * 105082 * @internal 105083 */ 105084 105085 this.afterPreactivation = () => (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(void 0); 105086 /** 105087 * A strategy for extracting and merging URLs. 105088 * Used for AngularJS to Angular migrations. 105089 */ 105090 105091 105092 this.urlHandlingStrategy = new DefaultUrlHandlingStrategy(); 105093 /** 105094 * A strategy for re-using routes. 105095 */ 105096 105097 this.routeReuseStrategy = new DefaultRouteReuseStrategy(); 105098 /** 105099 * How to handle a navigation request to the current URL. One of: 105100 * 105101 * - `'ignore'` : The router ignores the request. 105102 * - `'reload'` : The router reloads the URL. Use to implement a "refresh" feature. 105103 * 105104 * Note that this only configures whether the Route reprocesses the URL and triggers related 105105 * action and events like redirects, guards, and resolvers. By default, the router re-uses a 105106 * component instance when it re-navigates to the same component type without visiting a different 105107 * component first. This behavior is configured by the `RouteReuseStrategy`. In order to reload 105108 * routed components on same url navigation, you need to set `onSameUrlNavigation` to `'reload'` 105109 * _and_ provide a `RouteReuseStrategy` which returns `false` for `shouldReuseRoute`. 105110 */ 105111 105112 this.onSameUrlNavigation = 'ignore'; 105113 /** 105114 * How to merge parameters, data, resolved data, and title from parent to child 105115 * routes. One of: 105116 * 105117 * - `'emptyOnly'` : Inherit parent parameters, data, and resolved data 105118 * for path-less or component-less routes. 105119 * - `'always'` : Inherit parent parameters, data, and resolved data 105120 * for all child routes. 105121 */ 105122 105123 this.paramsInheritanceStrategy = 'emptyOnly'; 105124 /** 105125 * Determines when the router updates the browser URL. 105126 * By default (`"deferred"`), updates the browser URL after navigation has finished. 105127 * Set to `'eager'` to update the browser URL at the beginning of navigation. 105128 * You can choose to update early so that, if navigation fails, 105129 * you can show an error message with the URL that failed. 105130 */ 105131 105132 this.urlUpdateStrategy = 'deferred'; 105133 /** 105134 * Enables a bug fix that corrects relative link resolution in components with empty paths. 105135 * @see `RouterModule` 105136 * 105137 * @deprecated 105138 */ 105139 105140 this.relativeLinkResolution = 'corrected'; 105141 /** 105142 * Configures how the Router attempts to restore state when a navigation is cancelled. 105143 * 105144 * 'replace' - Always uses `location.replaceState` to set the browser state to the state of the 105145 * router before the navigation started. This means that if the URL of the browser is updated 105146 * _before_ the navigation is canceled, the Router will simply replace the item in history rather 105147 * than trying to restore to the previous location in the session history. This happens most 105148 * frequently with `urlUpdateStrategy: 'eager'` and navigations with the browser back/forward 105149 * buttons. 105150 * 105151 * 'computed' - Will attempt to return to the same index in the session history that corresponds 105152 * to the Angular route when the navigation gets cancelled. For example, if the browser back 105153 * button is clicked and the navigation is cancelled, the Router will trigger a forward navigation 105154 * and vice versa. 105155 * 105156 * Note: the 'computed' option is incompatible with any `UrlHandlingStrategy` which only 105157 * handles a portion of the URL because the history restoration navigates to the previous place in 105158 * the browser history rather than simply resetting a portion of the URL. 105159 * 105160 * The default value is `replace`. 105161 * 105162 */ 105163 105164 this.canceledNavigationResolution = 'replace'; 105165 105166 const onLoadStart = r => this.triggerEvent(new RouteConfigLoadStart(r)); 105167 105168 const onLoadEnd = r => this.triggerEvent(new RouteConfigLoadEnd(r)); 105169 105170 this.configLoader = injector.get(RouterConfigLoader); 105171 this.configLoader.onLoadEndListener = onLoadEnd; 105172 this.configLoader.onLoadStartListener = onLoadStart; 105173 this.ngModule = injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModuleRef); 105174 this.console = injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵConsole"]); 105175 const ngZone = injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone); 105176 this.isNgZoneEnabled = ngZone instanceof _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone && _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone.isInAngularZone(); 105177 this.resetConfig(config); 105178 this.currentUrlTree = createEmptyUrlTree(); 105179 this.rawUrlTree = this.currentUrlTree; 105180 this.browserUrlTree = this.currentUrlTree; 105181 this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType); 105182 this.transitions = new rxjs__WEBPACK_IMPORTED_MODULE_3__.BehaviorSubject({ 105183 id: 0, 105184 targetPageId: 0, 105185 currentUrlTree: this.currentUrlTree, 105186 currentRawUrl: this.currentUrlTree, 105187 extractedUrl: this.urlHandlingStrategy.extract(this.currentUrlTree), 105188 urlAfterRedirects: this.urlHandlingStrategy.extract(this.currentUrlTree), 105189 rawUrl: this.currentUrlTree, 105190 extras: {}, 105191 resolve: null, 105192 reject: null, 105193 promise: Promise.resolve(true), 105194 source: 'imperative', 105195 restoredState: null, 105196 currentSnapshot: this.routerState.snapshot, 105197 targetSnapshot: null, 105198 currentRouterState: this.routerState, 105199 targetRouterState: null, 105200 guards: { 105201 canActivateChecks: [], 105202 canDeactivateChecks: [] 105203 }, 105204 guardsResult: null 105205 }); 105206 this.navigations = this.setupNavigations(this.transitions); 105207 this.processNavigations(); 105208 } 105209 /** 105210 * The ɵrouterPageId of whatever page is currently active in the browser history. This is 105211 * important for computing the target page id for new navigations because we need to ensure each 105212 * page id in the browser history is 1 more than the previous entry. 105213 */ 105214 105215 105216 get browserPageId() { 105217 return this.location.getState()?.ɵrouterPageId; 105218 } 105219 105220 setupNavigations(transitions) { 105221 const eventsSubject = this.events; 105222 return transitions.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.filter)(t => t.id !== 0), // Extract URL 105223 (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(t => ({ ...t, 105224 extractedUrl: this.urlHandlingStrategy.extract(t.rawUrl) 105225 })), // Using switchMap so we cancel executing navigations when a new one comes in 105226 (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(overallTransitionState => { 105227 let completed = false;
105228 let errored = false; 105229 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(overallTransitionState).pipe( // Store the Navigation object 105230 (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => { 105231 this.currentNavigation = { 105232 id: t.id, 105233 initialUrl: t.rawUrl, 105234 extractedUrl: t.extractedUrl, 105235 trigger: t.source, 105236 extras: t.extras, 105237 previousNavigation: this.lastSuccessfulNavigation ? { ...this.lastSuccessfulNavigation, 105238 previousNavigation: null 105239 } : null 105240 }; 105241 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(t => { 105242 const browserUrlTree = this.browserUrlTree.toString(); 105243 const urlTransition = !this.navigated || t.extractedUrl.toString() !== browserUrlTree || // Navigations which succeed or ones which fail and are cleaned up 105244 // correctly should result in `browserUrlTree` and `currentUrlTree` 105245 // matching. If this is not the case, assume something went wrong and 105246 // try processing the URL again. 105247 browserUrlTree !== this.currentUrlTree.toString(); 105248 const processCurrentUrl = (this.onSameUrlNavigation === 'reload' ? true : urlTransition) && this.urlHandlingStrategy.shouldProcessUrl(t.rawUrl); 105249 105250 if (processCurrentUrl) { 105251 // If the source of the navigation is from a browser event, the URL is 105252 // already updated. We already need to sync the internal state. 105253 if (isBrowserTriggeredNavigation(t.source)) { 105254 this.browserUrlTree = t.extractedUrl; 105255 } 105256 105257 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(t).pipe( // Fire NavigationStart event 105258 (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(t => { 105259 const transition = this.transitions.getValue(); 105260 eventsSubject.next(new NavigationStart(t.id, this.serializeUrl(t.extractedUrl), t.source, t.restoredState)); 105261 105262 if (transition !== this.transitions.getValue()) { 105263 return rxjs__WEBPACK_IMPORTED_MODULE_26__.EMPTY; 105264 } // This delay is required to match old behavior that forced 105265 // navigation to always be async 105266 105267 105268 return Promise.resolve(t); 105269 }), // ApplyRedirects 105270 applyRedirects(this.ngModule.injector, this.configLoader, this.urlSerializer, this.config), // Update the currentNavigation 105271 // `urlAfterRedirects` is guaranteed to be set after this point 105272 (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => { 105273 this.currentNavigation = { ...this.currentNavigation, 105274 finalUrl: t.urlAfterRedirects 105275 }; 105276 overallTransitionState.urlAfterRedirects = t.urlAfterRedirects; 105277 }), // Recognize 105278 recognize(this.ngModule.injector, this.rootComponentType, this.config, this.urlSerializer, this.paramsInheritanceStrategy, this.relativeLinkResolution), // Update URL if in `eager` update mode 105279 (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => { 105280 overallTransitionState.targetSnapshot = t.targetSnapshot; 105281 105282 if (this.urlUpdateStrategy === 'eager') { 105283 if (!t.extras.skipLocationChange) { 105284 const rawUrl = this.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl); 105285 this.setBrowserUrl(rawUrl, t); 105286 } 105287 105288 this.browserUrlTree = t.urlAfterRedirects; 105289 } // Fire RoutesRecognized 105290 105291 105292 const routesRecognized = new RoutesRecognized(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot); 105293 eventsSubject.next(routesRecognized); 105294 })); 105295 } else { 105296 const processPreviousUrl = urlTransition && this.rawUrlTree && this.urlHandlingStrategy.shouldProcessUrl(this.rawUrlTree); 105297 /* When the current URL shouldn't be processed, but the previous one 105298 * was, we handle this "error condition" by navigating to the 105299 * previously successful URL, but leaving the URL intact.*/ 105300 105301 if (processPreviousUrl) { 105302 const { 105303 id, 105304 extractedUrl, 105305 source, 105306 restoredState, 105307 extras 105308 } = t; 105309 const navStart = new NavigationStart(id, this.serializeUrl(extractedUrl), source, restoredState); 105310 eventsSubject.next(navStart); 105311 const targetSnapshot = createEmptyState(extractedUrl, this.rootComponentType).snapshot; 105312 overallTransitionState = { ...t, 105313 targetSnapshot, 105314 urlAfterRedirects: extractedUrl, 105315 extras: { ...extras, 105316 skipLocationChange: false, 105317 replaceUrl: false 105318 } 105319 }; 105320 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(overallTransitionState); 105321 } else { 105322 /* When neither the current or previous URL can be processed, do 105323 * nothing other than update router's internal reference to the 105324 * current "settled" URL. This way the next navigation will be coming 105325 * from the current URL in the browser. 105326 */ 105327 this.rawUrlTree = t.rawUrl; 105328 t.resolve(null); 105329 return rxjs__WEBPACK_IMPORTED_MODULE_26__.EMPTY; 105330 } 105331 } 105332 }), // --- GUARDS --- 105333 (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => { 105334 const guardsStart = new GuardsCheckStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot); 105335 this.triggerEvent(guardsStart); 105336 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(t => { 105337 overallTransitionState = { ...t, 105338 guards: getAllRouteGuards(t.targetSnapshot, t.currentSnapshot, this.rootContexts) 105339 }; 105340 return overallTransitionState; 105341 }), checkGuards(this.ngModule.injector, evt => this.triggerEvent(evt)), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => { 105342 overallTransitionState.guardsResult = t.guardsResult; 105343 105344 if (isUrlTree(t.guardsResult)) { 105345 throw redirectingNavigationError(this.urlSerializer, t.guardsResult); 105346 } 105347 105348 const guardsEnd = new GuardsCheckEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot, !!t.guardsResult); 105349 this.triggerEvent(guardsEnd); 105350 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.filter)(t => { 105351 if (!t.guardsResult) { 105352 this.restoreHistory(t); 105353 this.cancelNavigationTransition(t, '', 3 105354 /* NavigationCancellationCode.GuardRejected */ 105355 ); 105356 return false;
105357 } 105358 105359 return true; 105360 }), // --- RESOLVE --- 105361 switchTap(t => { 105362 if (t.guards.canActivateChecks.length) { 105363 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(t).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => { 105364 const resolveStart = new ResolveStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot); 105365 this.triggerEvent(resolveStart); 105366 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.switchMap)(t => { 105367 let dataResolved = false; 105368 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(t).pipe(resolveData(this.paramsInheritanceStrategy, this.ngModule.injector), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)({ 105369 next: () => dataResolved = true, 105370 complete: () => { 105371 if (!dataResolved) { 105372 this.restoreHistory(t); 105373 this.cancelNavigationTransition(t, NG_DEV_MODE$2 ? `At least one route resolver didn't emit any value.` : '', 2 105374 /* NavigationCancellationCode.NoDataFromResolver */ 105375 ); 105376 } 105377 } 105378 })); 105379 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => { 105380 const resolveEnd = new ResolveEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot); 105381 this.triggerEvent(resolveEnd); 105382 })); 105383 } 105384 105385 return undefined; 105386 }), // --- LOAD COMPONENTS --- 105387 switchTap(t => { 105388 const loadComponents = route => { 105389 const loaders = []; 105390 105391 if (route.routeConfig?.loadComponent && !route.routeConfig._loadedComponent) { 105392 loaders.push(this.configLoader.loadComponent(route.routeConfig).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(loadedComponent => { 105393 route.component = loadedComponent; 105394 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(() => void 0))); 105395 } 105396 105397 for (const child of route.children) { 105398 loaders.push(...loadComponents(child)); 105399 } 105400 105401 return loaders; 105402 }; 105403 105404 return (0,rxjs__WEBPACK_IMPORTED_MODULE_7__.combineLatest)(loadComponents(t.targetSnapshot.root)).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_24__.defaultIfEmpty)(), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.take)(1)); 105405 }), switchTap(() => this.afterPreactivation()), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(t => { 105406 const targetRouterState = createRouterState(this.routeReuseStrategy, t.targetSnapshot, t.currentRouterState); 105407 overallTransitionState = { ...t, 105408 targetRouterState 105409 }; 105410 return overallTransitionState; 105411 }), 105412 /* Once here, we are about to activate synchronously. The assumption is 105413 this will succeed, and user code may read from the Router service. 105414 Therefore before activation, we need to update router properties storing 105415 the current URL and the RouterState, as well as updated the browser URL. 105416 All this should happen *before* activating. */ 105417 (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)(t => { 105418 this.currentUrlTree = t.urlAfterRedirects; 105419 this.rawUrlTree = this.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl); 105420 this.routerState = t.targetRouterState; 105421 105422 if (this.urlUpdateStrategy === 'deferred') { 105423 if (!t.extras.skipLocationChange) { 105424 this.setBrowserUrl(this.rawUrlTree, t); 105425 } 105426 105427 this.browserUrlTree = t.urlAfterRedirects; 105428 } 105429 }), activateRoutes(this.rootContexts, this.routeReuseStrategy, evt => this.triggerEvent(evt)), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_17__.tap)({ 105430 next() { 105431 completed = true; 105432 }, 105433 105434 complete() { 105435 completed = true; 105436 } 105437 105438 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_29__.finalize)(() => { 105439 /* When the navigation stream finishes either through error or success, 105440 * we set the `completed` or `errored` flag. However, there are some 105441 * situations where we could get here without either of those being set. 105442 * For instance, a redirect during NavigationStart. Therefore, this is a 105443 * catch-all to make sure the NavigationCancel event is fired
105443when a 105444 * navigation gets cancelled but not caught by other means. */ 105445 if (!completed && !errored) { 105446 const cancelationReason = NG_DEV_MODE$2 ? `Navigation ID ${overallTransitionState.id} is not equal to the current navigation id ${this.navigationId}` : ''; 105447 this.cancelNavigationTransition(overallTransitionState, cancelationReason, 1 105448 /* NavigationCancellationCode.SupersededByNewNavigation */ 105449 ); 105450 } // Only clear current navigation if it is still set to the one that 105451 // finalized. 105452 105453 105454 if (this.currentNavigation?.id === overallTransitionState.id) { 105455 this.currentNavigation = null; 105456 } 105457 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)(e => { 105458 errored = true; 105459 /* This error type is issued during Redirect, and is handled as a 105460 * cancellation rather than an error. */ 105461 105462 if (isNavigationCancelingError$1(e)) { 105463 if (!isRedirectingNavigationCancelingError$1(e)) { 105464 // Set property only if we're not redirecting. If we landed on a page 105465 // and redirect to `/` route, the new navigation is going to see the 105466 // `/` isn't a change from the default currentUrlTree and won't 105467 // navigate. This is only applicable with initial navigation, so 105468 // setting `navigated` only when not redirecting resolves this 105469 // scenario. 105470 this.navigated = true; 105471 this.restoreHistory(overallTransitionState, true); 105472 } 105473 105474 const navCancel = new NavigationCancel(overallTransitionState.id, this.serializeUrl(overallTransitionState.extractedUrl), e.message, e.cancellationCode); 105475 eventsSubject.next(navCancel); // When redirecting, we need to delay resolving the navigation 105476 // promise and push it to the redirect navigation 105477 105478 if (!isRedirectingNavigationCancelingError$1(e)) { 105479 overallTransitionState.resolve(false); 105480 } else { 105481 const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree); 105482 const extras = { 105483 skipLocationChange: overallTransitionState.extras.skipLocationChange, 105484 // The URL is already updated at this point if we have 'eager' URL 105485 // updates or if the navigation was triggered by the browser (back 105486 // button, URL bar, etc). We want to replace that item in history 105487 // if the navigation is rejected. 105488 replaceUrl: this.urlUpdateStrategy === 'eager' || isBrowserTriggeredNavigation(overallTransitionState.source) 105489 }; 105490 this.scheduleNavigation(mergedTree, 'imperative', null, extras, { 105491 resolve: overallTransitionState.resolve, 105492 reject: overallTransitionState.reject, 105493 promise: overallTransitionState.promise 105494 }); 105495 } 105496 /* All other errors should reset to the router's internal URL reference 105497 * to the pre-error state. */ 105498 105499 } else { 105500 this.restoreHistory(overallTransitionState, true); 105501 const navError = new NavigationError(overallTransitionState.id, this.serializeUrl(overallTransitionState.extractedUrl), e, overallTransitionState.targetSnapshot ?? undefined); 105502 eventsSubject.next(navError); 105503 105504 try { 105505 overallTransitionState.resolve(this.errorHandler(e)); 105506 } catch (ee) { 105507 overallTransitionState.reject(ee); 105508 } 105509 } 105510 105511 return rxjs__WEBPACK_IMPORTED_MODULE_26__.EMPTY; 105512 })); // TODO(jasonaden): remove cast once g3 is on updated TypeScript 105513 })); 105514 } 105515 /** 105516 * @internal 105517 * TODO: this should be removed once the constructor of the router made internal 105518 */ 105519 105520 105521 resetRootComponentType(rootComponentType) { 105522 this.rootComponentType = rootComponentType; // TODO: vsavkin router 4.0 should make the root component set to null 105523 // this will simplify the lifecycle of the router. 105524 105525 this.routerState.root.component = this.rootComponentType; 105526 } 105527 105528 setTransition(t) { 105529 this.transitions.next({ ...this.transitions.value, 105530 ...t 105531 }); 105532 } 105533 /** 105534 * Sets up the location change listener and performs the initial navigation. 105535 */ 105536 105537 105538 initialNavigation() { 105539 this.setUpLocationChangeListener(); 105540 105541 if (this.navigationId === 0) { 105542 this.navigateByUrl(this.location.path(true), { 105543 replaceUrl: true 105544 }); 105545 } 105546 } 105547 /** 105548 * Sets up the location change listener. This listener detects navigations triggered from outside 105549 * the Router (the browser back/forward buttons, for example) and schedules a corresponding Router 105550 * navigation so that the correct events, guards, etc. are triggered. 105551 */ 105552 105553 105554 setUpLocationChangeListener() { 105555 // Don't need to use Zone.wrap any more, because zone.js 105556 // already patch onPopState, so location change callback will 105557 // run into ngZone 105558 if (!this.locationSubscription) { 105559 this.locationSubscription = this.location.subscribe(event => { 105560 const source = event['type'] === 'popstate' ? 'popstate' : 'hashchange'; 105561 105562 if (source === 'popstate') { 105563 // The `setTimeout` was added in #12160 and is likely to support Angular/AngularJS 105564 // hybrid apps. 105565 setTimeout(() => { 105566 const extras = { 105567 replaceUrl: true 105568 }; // Navigations coming from Angular router have a navigationId state 105569 // property. When this exists, restore the state. 105570 105571 const state = event.state?.navigationId ? event.state : null; 105572 105573 if (state) { 105574 const stateCopy = { ...state 105575 }; 105576 delete stateCopy.navigationId; 105577 delete stateCopy.ɵrouterPageId; 105578 105579 if (Object.keys(stateCopy).length !== 0) { 105580 extras.state = stateCopy; 105581 } 105582 } 105583 105584 const urlTree = this.parseUrl(event['url']); 105585 this.scheduleNavigation(urlTree, source, state, extras); 105586 }, 0); 105587 } 105588 }); 105589 } 105590 } 105591 /** The current URL. */ 105592 105593 105594 get url() { 105595 return this.serializeUrl(this.currentUrlTree); 105596 } 105597 /** 105598 * Returns the current `Navigation` object when the router is navigating, 105599 * and `null` when idle. 105600 */ 105601 105602 105603 getCurrentNavigation() { 105604 return this.currentNavigation; 105605 } 105606 /** @internal */ 105607 105608 105609 triggerEvent(event) { 105610 this.events.next(event); 105611 } 105612 /** 105613 * Resets the route configuration used for navigation and generating links. 105614 * 105615 * @param config The route array for the new configuration. 105616 * 105617 * @usageNotes 105618 * 105619 * ``` 105620 * router.resetConfig([ 105621 * { path: 'team/:id', component: TeamCmp, children: [ 105622 * { path: 'simple', component: SimpleCmp }, 105623 * { path: 'user/:name', component: UserCmp } 105624 * ]} 105625 * ]); 105626 * ``` 105627 */ 105628 105629 105630 resetConfig(config) { 105631 NG_DEV_MODE$2 && validateConfig(config); 105632 this.config = config.map(standardizeConfig); 105633 this.navigated = false;
105634 this.lastSuccessfulId = -1; 105635 } 105636 /** @nodoc */ 105637 105638 105639 ngOnDestroy() { 105640 this.dispose(); 105641 } 105642 /** Disposes of the router. */ 105643 105644 105645 dispose() { 105646 this.transitions.complete(); 105647 105648 if (this.locationSubscription) { 105649 this.locationSubscription.unsubscribe(); 105650 this.locationSubscription = undefined; 105651 } 105652 105653 this.disposed = true; 105654 } 105655 /** 105656 * Appends URL segments to the current URL tree to create a new URL tree. 105657 * 105658 * @param commands An array of URL fragments with which to construct the new URL tree. 105659 * If the path is static, can be the literal URL string. For a dynamic path, pass an array of path 105660 * segments, followed by the parameters for each segment. 105661 * The fragments are applied to the current URL tree or the one provided in the `relativeTo` 105662 * property of the options object, if supplied. 105663 * @param navigationExtras Options that control the navigation strategy. 105664 * @returns The new URL tree. 105665 * 105666 * @usageNotes 105667 * 105668 * ``` 105669 * // create /team/33/user/11 105670 * router.createUrlTree(['/team', 33, 'user', 11]); 105671 * 105672 * // create /team/33;expand=true/user/11 105673 * router.createUrlTree(['/team', 33, {expand: true}, 'user', 11]); 105674 * 105675 * // you can collapse static segments like this (this works only with the first passed-in value): 105676 * router.createUrlTree(['/team/33/user', userId]); 105677 * 105678 * // If the first segment can contain slashes, and you do not want the router to split it, 105679 * // you can do the following: 105680 * router.createUrlTree([{segmentPath: '/one/two'}]); 105681 * 105682 * // create /team/33/(user/11//right:chat) 105683 * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: 'chat'}}]); 105684 * 105685 * // remove the right secondary node 105686 * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: null}}]); 105687 * 105688 * // assuming the current url is `/team/33/user/11` and the route points to `user/11` 105689 * 105690 * // navigate to /team/33/user/11/details 105691 * router.createUrlTree(['details'], {relativeTo: route}); 105692 * 105693 * // navigate to /team/33/user/22 105694 * router.createUrlTree(['../22'], {relativeTo: route}); 105695 * 105696 * // navigate to /team/44/user/22 105697 * router.createUrlTree(['../../team/44/user/22'], {relativeTo: route}); 105698 * 105699 * Note that a value of `null` or `undefined` for `relativeTo` indicates that the 105700 * tree should be created relative to the root. 105701 * ``` 105702 */ 105703 105704 105705 createUrlTree(commands, navigationExtras = {}) { 105706 const { 105707 relativeTo, 105708 queryParams, 105709 fragment, 105710 queryParamsHandling, 105711 preserveFragment 105712 } = navigationExtras; 105713 const a = relativeTo || this.routerState.root; 105714 const f = preserveFragment ? this.currentUrlTree.fragment : fragment; 105715 let q = null; 105716 105717 switch (queryParamsHandling) { 105718 case 'merge': 105719 q = { ...this.currentUrlTree.queryParams, 105720 ...queryParams 105721 }; 105722 break; 105723 105724 case 'preserve': 105725 q = this.currentUrlTree.queryParams; 105726 break; 105727 105728 default: 105729 q = queryParams || null; 105730 } 105731 105732 if (q !== null) { 105733 q = this.removeEmptyProps(q); 105734 } 105735 105736 return createUrlTree(a, this.currentUrlTree, commands, q, f ?? null); 105737 } 105738 /** 105739 * Navigates to a view using an absolute route path. 105740 * 105741 * @param url An absolute path for a defined route. The function does not apply any delta to the 105742 * current URL. 105743 * @param extras An object containing properties that modify the navigation strategy. 105744 * 105745 * @returns A Promise that resolves to 'true' when navigation succeeds, 105746 * to 'false' when navigation fails, or is rejected on error. 105747 * 105748 * @usageNotes 105749 * 105750 * The following calls request navigation to an absolute path. 105751 * 105752 * ``` 105753 * router.navigateByUrl("/team/33/user/11"); 105754 * 105755 * // Navigate without updating the URL 105756 * router.navigateByUrl("/team/33/user/11", { skipLocationChange: true }); 105757 * ``` 105758 * 105759 * @see [Routing and Navigation guide](guide/router) 105760 * 105761 */ 105762 105763 105764 navigateByUrl(url, extras = { 105765 skipLocationChange: false 105766 }) { 105767 if (typeof ngDevMode === 'undefined' || ngDevMode && this.isNgZoneEnabled && !_angular_core__WEBPACK_IMPORTED_MODULE_0__.NgZone.isInAngularZone()) { 105768 this.console.warn(`Navigation triggered outside Angular zone, did
105768you forget to call 'ngZone.run()'?`); 105769 } 105770 105771 const urlTree = isUrlTree(url) ? url : this.parseUrl(url); 105772 const mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree); 105773 return this.scheduleNavigation(mergedTree, 'imperative', null, extras); 105774 } 105775 /** 105776 * Navigate based on the provided array of commands and a starting point. 105777 * If no starting route is provided, the navigation is absolute. 105778 * 105779 * @param commands An array of URL fragments with which to construct the target URL. 105780 * If the path is static, can be the literal URL string. For a dynamic path, pass an array of path 105781 * segments, followed by the parameters for each segment. 105782 * The fragments are applied to the current URL or the one provided in the `relativeTo` property 105783 * of the options object, if supplied. 105784 * @param extras An options object that determines how the URL should be constructed or 105785 * interpreted. 105786 * 105787 * @returns A Promise that resolves to `true` when navigation succeeds, to `false` when navigation 105788 * fails, 105789 * or is rejected on error. 105790 * 105791 * @usageNotes 105792 * 105793 * The following calls request navigation to a dynamic route path relative to the current URL. 105794 * 105795 * ``` 105796 * router.navigate(['team', 33, 'user', 11], {relativeTo: route}); 105797 * 105798 * // Navigate without updating the URL, overriding the default behavior 105799 * router.navigate(['team', 33, 'user', 11], {relativeTo: route, skipLocationChange: true}); 105800 * ``` 105801 * 105802 * @see [Routing and Navigation guide](guide/router) 105803 * 105804 */ 105805 105806 105807 navigate(commands, extras = { 105808 skipLocationChange: false 105809 }) { 105810 validateCommands(commands); 105811 return this.navigateByUrl(this.createUrlTree(commands, extras), extras); 105812 } 105813 /** Serializes a `UrlTree` into a string */ 105814 105815 105816 serializeUrl(url) { 105817 return this.urlSerializer.serialize(url); 105818 } 105819 /** Parses a string into a `UrlTree` */ 105820 105821 105822 parseUrl(url) { 105823 let urlTree; 105824 105825 try { 105826 urlTree = this.urlSerializer.parse(url); 105827 } catch (e) { 105828 urlTree = this.malformedUriErrorHandler(e, this.urlSerializer, url); 105829 } 105830 105831 return urlTree; 105832 } 105833 105834 isActive(url, matchOptions) { 105835 let options; 105836 105837 if (matchOptions === true) { 105838 options = { ...exactMatchOptions 105839 }; 105840 } else if (matchOptions === false) { 105841 options = { ...subsetMatchOptions 105842 }; 105843 } else { 105844 options = matchOptions; 105845 } 105846 105847 if (isUrlTree(url)) { 105848 return containsTree(this.currentUrlTree, url, options); 105849 } 105850 105851 const urlTree = this.parseUrl(url); 105852 return containsTree(this.currentUrlTree, urlTree, options); 105853 } 105854 105855 removeEmptyProps(params) { 105856 return Object.keys(params).reduce((result, key) => { 105857 const value = params[key]; 105858 105859 if (value !== null && value !== undefined) { 105860 result[key] = value; 105861 } 105862 105863 return result; 105864 }, {}); 105865 } 105866 105867 processNavigations() { 105868 this.navigations.subscribe(t => { 105869 this.navigated = true; 105870 this.lastSuccessfulId = t.id; 105871 this.currentPageId = t.targetPageId; 105872 this.events.next(new NavigationEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(this.currentUrlTree))); 105873 this.lastSuccessfulNavigation = this.currentNavigation; 105874 this.titleStrategy?.updateTitle(this.routerState.snapshot); 105875 t.resolve(true); 105876 }, e => { 105877 this.console.warn(`Unhandled Navigation Error: ${e}`); 105878 }); 105879 } 105880 105881 scheduleNavigation(rawUrl, source, restoredState, extras, priorPromise) { 105882 if (this.disposed) { 105883 return Promise.resolve(false); 105884 } 105885 105886 let resolve; 105887 let reject; 105888 let promise; 105889 105890 if (priorPromise) { 105891 resolve = priorPromise.resolve; 105892 reject = priorPromise.reject; 105893 promise = priorPromise.promise; 105894 } else { 105895 promise = new Promise((res, rej) => { 105896 resolve = res; 105897 reject = rej; 105898 }); 105899 } 105900 105901 const id = ++this.navigationId; 105902 let targetPageId; 105903 105904 if (this.canceledNavigationResolution === 'computed') { 105905 const isInitialPage = this.currentPageId === 0; 105906 105907 if (isInitialPage) { 105908 restoredState = this.location.getState(); 105909 } // If the `ɵrouterPageId` exist in the state then `targetpageId` should have the value of 105910 // `ɵrouterPageId`. This is the case for something like a page refresh where we assign the 105911 // target id to the previously set value for that page. 105912 105913 105914 if (restoredState && restoredState.ɵrouterPageId) { 105915 targetPageId = restoredState.ɵrouterPageId; 105916 } else { 105917 // If we're replacing the URL or doing a silent navigation, we do not want to increment the 105918 // page id because we aren't pushing a new entry to history. 105919 if (extras.replaceUrl || extras.skipLocationChange) { 105920 targetPageId = this.browserPageId ?? 0; 105921 } else { 105922 targetPageId = (this.browserPageId ?? 0) + 1; 105923 } 105924 } 105925 } else { 105926 // This is unused when `canceledNavigationResolution` is not computed. 105927 targetPageId = 0; 105928 } 105929 105930 this.setTransition({ 105931 id, 105932 targetPageId, 105933 source, 105934 restoredState, 105935 currentUrlTree: this.currentUrlTree, 105936 currentRawUrl: this.rawUrlTree, 105937 rawUrl, 105938 extras, 105939 resolve, 105940 reject, 105941 promise, 105942 currentSnapshot: this.routerState.snapshot, 105943 currentRouterState: this.routerState 105944 }); // Make sure that the error is propagated even though `processNavigations` catch 105945 // handler does not rethrow 105946 105947 return promise.catch(e => { 105948 return Promise.reject(e); 105949 }); 105950 } 105951 105952 setBrowserUrl(url, t) { 105953 const path = this.urlSerializer.serialize(url); 105954 const state = { ...t.extras.state, 105955 ...this.generateNgRouterState(t.id, t.targetPageId) 105956 }; 105957 105958 if (this.location.isCurrentPathEqualTo(path) || !!t.extras.replaceUrl) { 105959 this.location.replaceState(path, '', state); 105960 } else { 105961 this.location.go(path, '', state); 105962 } 105963 } 105964 /** 105965 * Performs the necessary rollback action to restore the browser URL to the 105966 * state before the transition. 105967 */ 105968 105969 105970 restoreHistory(t, restoringFromCaughtError = false) { 105971 if (this.canceledNavigationResolution === 'computed') { 105972 const targetPagePosition = this.currentPageId - t.targetPageId; // The navigator change the location before triggered the browser event, 105973 // so we need to go back to the current url if the navigation is canceled. 105974 // Also, when navigation gets cancelled while using url update strategy eager, then we need to 105975 // go back. Because, when `urlUpdateStrategy` is `eager`; `setBrowserUrl` method is called 105976 // before any verification. 105977 105978 const browserUrlUpdateOccurred = t.source === 'popstate' || this.urlUpdateStrategy === 'eager' || this.currentUrlTree === this.currentNavigation?.finalUrl; 105979 105980 if (browserUrlUpdateOccurred && targetPagePosition !== 0) { 105981 this.location.historyGo(targetPagePosition); 105982 } else if (this.currentUrlTree === this.currentNavigation?.finalUrl && targetPagePosition === 0) { 105983 // We got to the activation stage (where currentUrlTree is set to the navigation's 105984 // finalUrl), but we weren't moving anywhere in history (skipLocationChange or replaceUrl). 105985 // We still need to reset the router state back to what it was when the navigation started. 105986 this.resetState(t); // TODO(atscott): resetting the `browserUrlTree` should really be done in `resetState`. 105987 // Investigate if this can be done by running TGP. 105988 105989 this.browserUrlTree = t.currentUrlTree; 105990 this.resetUrlToCurrentUrlTree(); 105991 } else {// The browser URL and router state was not updated before the navigation cancelled so 105992 // there's no restoration needed. 105993 } 105994 } else if (this.canceledNavigationResolution === 'replace') { 105995 // TODO(atscott): It seems like we should _always_ reset the state here. It would be a no-op 105996 // for `deferred` navigations that haven't change the internal state yet because guards 105997 // reject. For 'eager' navigations, it seems like we also really should reset the state 105998 // because the navigation was cancelled. Investigate if this can be done by running TGP. 105999 if (restoringFromCaughtError) { 106000 this.resetState(t); 106001 } 106002 106003 this.resetUrlToCurrentUrlTree(); 106004 } 106005 } 106006 106007 resetState(t) { 106008 this.routerState = t.currentRouterState; 106009 this.currentUrlTree = t.currentUrlTree; // Note here that we use the urlHandlingStrategy to get the reset `rawUrlTree` because it may be 106010 // configured to handle only part of the navigation URL. This means we would only want to reset 106011 // the part of the navigation handled by the Angular router rather than the whole URL. In 106012 // addition, the URLHandlingStrategy may be configured to specifically preserve parts of the URL 106013 // when merging, such as the query params so they are not lost on a refresh. 106014 106015 this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, t.rawUrl); 106016 } 106017 106018 resetUrlToCurrentUrlTree() { 106019 this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId)); 106020 } 106021 106022 cancelNavigationTransition(t, reason, code) {
106023 const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), reason, code); 106024 this.triggerEvent(navCancel); 106025 t.resolve(false); 106026 } 106027 106028 generateNgRouterState(navigationId, routerPageId) { 106029 if (this.canceledNavigationResolution === 'computed') { 106030 return { 106031 navigationId, 106032 ɵrouterPageId: routerPageId 106033 }; 106034 } 106035 106036 return { 106037 navigationId 106038 }; 106039 } 106040 106041} 106042 106043Router.ɵfac = function Router_Factory(t) { 106044 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinvalidFactory"](); 106045}; 106046 106047Router.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 106048 token: Router, 106049 factory: function () { 106050 return setupRouter(); 106051 }, 106052 providedIn: 'root' 106053}); 106054 106055(function () { 106056 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](Router, [{ 106057 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 106058 args: [{ 106059 providedIn: 'root', 106060 useFactory: setupRouter 106061 }] 106062 }], function () { 106063 return [{ 106064 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Type 106065 }, { 106066 type: UrlSerializer 106067 }, { 106068 type: ChildrenOutletContexts 106069 }, { 106070 type: _angular_common__WEBPACK_IMPORTED_MODULE_33__.Location 106071 }, { 106072 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector 106073 }, { 106074 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Compiler 106075 }, { 106076 type: undefined 106077 }]; 106078 }, null); 106079})(); 106080 106081function validateCommands(commands) { 106082 for (let i = 0; i < commands.length; i++) { 106083 const cmd = commands[i]; 106084 106085 if (cmd == null) { 106086 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4008 106087 /* RuntimeErrorCode.NULLISH_COMMAND */ 106088 , NG_DEV_MODE$2 && `The requested path contains ${cmd} segment at index ${i}`); 106089 } 106090 } 106091} 106092 106093function isBrowserTriggeredNavigation(source) { 106094 return source !== 'imperative'; 106095} 106096/** 106097 * @license 106098 * Copyright Google LLC All Rights Reserved. 106099 * 106100 * Use of this source code is governed by an MIT-style license that can be 106101 * found in the LICENSE file at https://angular.io/license 106102 */ 106103 106104/** 106105 * @description 106106 * 106107 * When applied to an element in a template, makes that element a link 106108 * that initiates navigation to a route. Navigation opens one or more routed components 106109 * in one or more `<router-outlet>` locations on the page. 106110 * 106111 * Given a route configuration `[{ path: 'user/:name', component: UserCmp }]`, 106112 * the following creates a static link to the route: 106113 * `<a routerLink="/user/bob">link to user component</a>` 106114 * 106115 * You can use dynamic values to generate the link. 106116 * For a dynamic link, pass an array of path segments, 106117 * followed by the params for each segment. 106118 * For example, `['/team', teamId, 'user', userName, {details: true}]` 106119 * generates a link to `/team/11/user/bob;details=true`. 106120 * 106121 * Multiple static segments can be merged into one term and combined with dynamic segments. 106122 * For example, `['/team/11/user', userName, {details: true}]` 106123 * 106124 * The input that you provide to the link is treated as a delta to the current URL. 106125 * For instance, suppose the current URL is `/user/(box//aux:team)`. 106126 * The link `<a [routerLink]="['/user/jim']">Jim</a>` creates the URL 106127 * `/user/(jim//aux:team)`. 106128 * See {@link Router#createUrlTree createUrlTree} for more information. 106129 * 106130 * @usageNotes 106131 * 106132 * You can use absolute or relative paths in a link, set query parameters, 106133 * control how parameters are handled, and keep a history of navigation states. 106134 * 106135 * ### Relative link paths 106136 * 106137 * The first segment name can be prepended with `/`, `./`, or `../`. 106138 * * If the first segment begins with `/`, the router looks up the route from the root of the 106139 * app. 106140 * * If the first segment begins with `./`, or doesn't begin with a slash, the router 106141 * looks in the children of the current activated route. 106142 * * If the first segment begins with `../`, the router goes up one level in the route tree. 106143 * 106144 * ### Setting and handling query params and fragments 106145 * 106146 * The following link adds a query parameter and a fragment to the generated URL: 106147 * 106148 * ``` 106149 * <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" fragment="education"> 106150 * link to user component 106151 * </a> 106152 * ``` 106153 * By default, the directive constructs the new URL using the given query parameters. 106154 * The example generates the link: `/user/bob?debug=true#education`. 106155 * 106156 * You can instruct the directive to handle query parameters differently 106157 * by specifying the `queryParamsHandling` option in the link. 106158 * Allowed values are: 106159 * 106160 * - `'merge'`: Merge the given `queryParams` into the current query params. 106161 * - `'preserve'`: Preserve the current query params. 106162 * 106163 * For example: 106164 * 106165 * ``` 106166 * <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" queryParamsHandling="merge"> 106167 * link to user component 106168 * </a> 106169 * ``` 106170 * 106171 * See {@link UrlCreationOptions.queryParamsHandling UrlCreationOptions#queryParamsHandling}. 106172 * 106173 * ### Preserving navigation history 106174 * 106175 * You can provide a `state` value to be persisted to the browser's 106176 * [`History.state` property](https://developer.mozilla.org/en-US/docs/Web/API/History#Properties). 106177 * For example: 106178 * 106179 * ``` 106180 * <a [routerLink]="['/user/bob']" [state]="{tracingId: 123}"> 106181 * link to user component 106182 * </a> 106183 * ``` 106184 * 106185 * Use {@link Router.getCurrentNavigation() Router#getCurrentNavigation} to retrieve a saved 106186 * navigation-state value. For example, to capture the `tracingId` during the `NavigationStart` 106187 * event: 106188 * 106189 * ``` 106190 * // Get NavigationStart events 106191 * router.events.pipe(filter(e => e instanceof NavigationStart)).subscribe(e => { 106192 * const navigation = router.getCurrentNavigation(); 106193 * tracingService.trace({id: navigation.extras.state.tracingId}); 106194 * }); 106195 * ``` 106196 * 106197 * @ngModule RouterModule 106198 * 106199 * @publicApi 106200 */ 106201 106202 106203class RouterLink { 106204 constructor(router, route, tabIndexAttribute, renderer, el) { 106205 this.router = router; 106206 this.route = route; 106207 this.tabIndexAttribute = tabIndexAttribute; 106208 this.renderer = renderer; 106209 this.el = el; 106210 this._preserveFragment = false;
106211 this._skipLocationChange = false; 106212 this._replaceUrl = false; 106213 this.commands = null; 106214 /** @internal */ 106215 106216 this.onChanges = new rxjs__WEBPACK_IMPORTED_MODULE_31__.Subject(); 106217 this.setTabIndexIfNotOnNativeEl('0'); 106218 } 106219 /** 106220 * Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the 106221 * `UrlCreationOptions`. 106222 * @see {@link UrlCreationOptions#preserveFragment UrlCreationOptions#preserveFragment} 106223 * @see {@link Router#createUrlTree Router#createUrlTree} 106224 */ 106225 106226 106227 set preserveFragment(preserveFragment) { 106228 this._preserveFragment = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"])(preserveFragment); 106229 } 106230 106231 get preserveFragment() { 106232 return this._preserveFragment; 106233 } 106234 /** 106235 * Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the 106236 * `NavigationBehaviorOptions`. 106237 * @see {@link NavigationBehaviorOptions#skipLocationChange NavigationBehaviorOptions#skipLocationChange} 106238 * @see {@link Router#navigateByUrl Router#navigateByUrl} 106239 */ 106240 106241 106242 set skipLocationChange(skipLocationChange) { 106243 this._skipLocationChange = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"])(skipLocationChange); 106244 } 106245 106246 get skipLocationChange() { 106247 return this._skipLocationChange; 106248 } 106249 /** 106250 * Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the 106251 * `NavigationBehaviorOptions`. 106252 * @see {@link NavigationBehaviorOptions#replaceUrl NavigationBehaviorOptions#replaceUrl} 106253 * @see {@link Router#navigateByUrl Router#navigateByUrl} 106254 */ 106255 106256 106257 set replaceUrl(replaceUrl) { 106258 this._replaceUrl = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"])(replaceUrl); 106259 } 106260 106261 get replaceUrl() { 106262 return this._replaceUrl; 106263 } 106264 /** 106265 * Modifies the tab index if there was not a tabindex attribute on the element during 106266 * instantiation. 106267 */ 106268 106269 106270 setTabIndexIfNotOnNativeEl(newTabIndex) { 106271 if (this.tabIndexAttribute != null 106272 /* both `null` and `undefined` */ 106273 ) { 106274 return; 106275 } 106276 106277 const renderer = this.renderer; 106278 const nativeElement = this.el.nativeElement; 106279 106280 if (newTabIndex !== null) { 106281 renderer.setAttribute(nativeElement, 'tabindex', newTabIndex); 106282 } else { 106283 renderer.removeAttribute(nativeElement, 'tabindex'); 106284 } 106285 } 106286 /** @nodoc */ 106287 106288 106289 ngOnChanges(changes) { 106290 // This is subscribed to by `RouterLinkActive` so that it knows to update when there are changes 106291 // to the RouterLinks it's tracking. 106292 this.onChanges.next(this); 106293 } 106294 /** 106295 * Commands to pass to {@link Router#createUrlTree Router#createUrlTree}. 106296 * - **array**: commands to pass to {@link Router#createUrlTree Router#createUrlTree}. 106297 * - **string**: shorthand for array of commands with just the string, i.e. `['/route']` 106298 * - **null|undefined**: effectively disables the `routerLink` 106299 * @see {@link Router#createUrlTree Router#createUrlTree} 106300 */ 106301 106302 106303 set routerLink(commands) { 106304 if (commands != null) { 106305 this.commands = Array.isArray(commands) ? commands : [commands]; 106306 this.setTabIndexIfNotOnNativeEl('0'); 106307 } else { 106308 this.commands = null; 106309 this.setTabIndexIfNotOnNativeEl(null); 106310 } 106311 } 106312 /** @nodoc */ 106313 106314 106315 onClick() { 106316 if (this.urlTree === null) { 106317 return true; 106318 } 106319 106320 const extras = { 106321 skipLocationChange: this.skipLocationChange, 106322 replaceUrl: this.replaceUrl, 106323 state: this.state 106324 }; 106325 this.router.navigateByUrl(this.urlTree, extras); 106326 return true; 106327 } 106328 106329 get urlTree() { 106330 if (this.commands === null) { 106331 return null; 106332 } 106333 106334 return this.router.createUrlTree(this.commands, { 106335 // If the `relativeTo` input is not defined, we want to use `this.route` by default. 106336 // Otherwise, we should use the value provided by the user in the input. 106337 relativeTo: this.relativeTo !== undefined ? this.relativeTo : this.route, 106338 queryParams: this.queryParams, 106339 fragment: this.fragment, 106340 queryParamsHandling: this.queryParamsHandling, 106341 preserveFragment: this.preserveFragment 106342 }); 106343 } 106344 106345} 106346 106347RouterLink.ɵfac = function RouterLink_Factory(t) { 106348 return new (t || RouterLink)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](Router), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ActivatedRoute), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinjectAttribute"]('tabindex'), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef)); 106349}; 106350 106351RouterLink.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 106352 type: RouterLink, 106353 selectors: [["", "routerLink", "", 5, "a", 5, "area"]], 106354 hostBindings: function RouterLink_HostBindings(rf, ctx) { 106355 if (rf & 1) { 106356 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("click", function RouterLink_click_HostBindingHandler() { 106357 return ctx.onClick(); 106358 }); 106359 } 106360 }, 106361 inputs: { 106362 queryParams: "queryParams", 106363 fragment: "fragment", 106364 queryParamsHandling: "queryParamsHandling", 106365 state: "state", 106366 relativeTo: "relativeTo", 106367 preserveFragment: "preserveFragment", 106368 skipLocationChange: "skipLocationChange", 106369 replaceUrl: "replaceUrl", 106370 routerLink: "routerLink" 106371 }, 106372 standalone: true, 106373 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]] 106374}); 106375 106376(function () { 106377 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterLink, [{ 106378 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 106379 args: [{
106380 selector: ':not(a):not(area)[routerLink]', 106381 standalone: true 106382 }] 106383 }], function () { 106384 return [{ 106385 type: Router 106386 }, { 106387 type: ActivatedRoute 106388 }, { 106389 type: undefined, 106390 decorators: [{ 106391 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Attribute, 106392 args: ['tabindex'] 106393 }] 106394 }, { 106395 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2 106396 }, { 106397 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef 106398 }]; 106399 }, { 106400 queryParams: [{ 106401 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106402 }], 106403 fragment: [{ 106404 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106405 }], 106406 queryParamsHandling: [{ 106407 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106408 }], 106409 state: [{ 106410 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106411 }], 106412 relativeTo: [{ 106413 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106414 }], 106415 preserveFragment: [{ 106416 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106417 }], 106418 skipLocationChange: [{ 106419 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106420 }], 106421 replaceUrl: [{ 106422 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106423 }], 106424 routerLink: [{ 106425 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106426 }], 106427 onClick: [{ 106428 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostListener, 106429 args: ['click'] 106430 }] 106431 }); 106432})(); 106433/** 106434 * @description 106435 * 106436 * Lets you link to specific routes in your app. 106437 * 106438 * See `RouterLink` for more information. 106439 * 106440 * @ngModule RouterModule 106441 * 106442 * @publicApi 106443 */ 106444 106445 106446class RouterLinkWithHref { 106447 constructor(router, route, locationStrategy) { 106448 this.router = router; 106449 this.route = route; 106450 this.locationStrategy = locationStrategy; 106451 this._preserveFragment = false; 106452 this._skipLocationChange = false; 106453 this._replaceUrl = false; 106454 this.commands = null; // the url displayed on the anchor element. 106455 // @HostBinding('attr.href') is used rather than @HostBinding() because it removes the 106456 // href attribute when it becomes `null`. 106457 106458 this.href = null; 106459 /** @internal */ 106460 106461 this.onChanges = new rxjs__WEBPACK_IMPORTED_MODULE_31__.Subject(); 106462 this.subscription = router.events.subscribe(s => { 106463 if (s instanceof NavigationEnd) { 106464 this.updateTargetUrlAndHref(); 106465 } 106466 }); 106467 } 106468 /** 106469 * Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the 106470 * `UrlCreationOptions`. 106471 * @see {@link UrlCreationOptions#preserveFragment UrlCreationOptions#preserveFragment} 106472 * @see {@link Router#createUrlTree Router#createUrlTree} 106473 */ 106474 106475 106476 set preserveFragment(preserveFragment) { 106477 this._preserveFragment = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"])(preserveFragment); 106478 } 106479 106480 get preserveFragment() { 106481 return this._preserveFragment; 106482 } 106483 /** 106484 * Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the 106485 * `NavigationBehaviorOptions`. 106486 * @see {@link NavigationBehaviorOptions#skipLocationChange NavigationBehaviorOptions#skipLocationChange} 106487 * @see {@link Router#navigateByUrl Router#navigateByUrl} 106488 */ 106489 106490 106491 set skipLocationChange(skipLocationChange) { 106492 this._skipLocationChange = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"])(skipLocationChange); 106493 } 106494 106495 get skipLocationChange() { 106496 return this._skipLocationChange; 106497 } 106498 /** 106499 * Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the 106500 * `NavigationBehaviorOptions`. 106501 * @see {@link NavigationBehaviorOptions#replaceUrl NavigationBehaviorOptions#replaceUrl} 106502 * @see {@link Router#navigateByUrl Router#navigateByUrl} 106503 */ 106504 106505 106506 set replaceUrl(replaceUrl) { 106507 this._replaceUrl = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵcoerceToBoolean"])(replaceUrl); 106508 } 106509 106510 get replaceUrl() { 106511 return this._replaceUrl; 106512 } 106513 /** 106514 * Commands to pass to {@link Router#createUrlTree Router#createUrlTree}. 106515 * - **array**: commands to pass to {@link Router#createUrlTree Router#createUrlTree}. 106516 * - **string**: shorthand for array of commands with just the string, i.e. `['/route']` 106517 * - **null|undefined**: Disables the link by removing the `href` 106518 * @see {@link Router#createUrlTree Router#createUrlTree} 106519 */ 106520 106521 106522 set routerLink(commands) { 106523 if (commands != null) { 106524 this.commands = Array.isArray(commands) ? commands : [commands]; 106525 } else { 106526 this.commands = null; 106527 } 106528 } 106529 /** @nodoc */ 106530 106531 106532 ngOnChanges(changes) { 106533 this.updateTargetUrlAndHref(); 106534 this.onChanges.next(this); 106535 } 106536 /** @nodoc */ 106537 106538 106539 ngOnDestroy() { 106540 this.subscription.unsubscribe(); 106541 } 106542 /** @nodoc */ 106543 106544
106545 onClick(button, ctrlKey, shiftKey, altKey, metaKey) { 106546 if (button !== 0 || ctrlKey || shiftKey || altKey || metaKey) { 106547 return true; 106548 } 106549 106550 if (typeof this.target === 'string' && this.target != '_self' || this.urlTree === null) { 106551 return true; 106552 } 106553 106554 const extras = { 106555 skipLocationChange: this.skipLocationChange, 106556 replaceUrl: this.replaceUrl, 106557 state: this.state 106558 }; 106559 this.router.navigateByUrl(this.urlTree, extras); 106560 return false; 106561 } 106562 106563 updateTargetUrlAndHref() { 106564 this.href = this.urlTree !== null ? this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(this.urlTree)) : null; 106565 } 106566 106567 get urlTree() { 106568 if (this.commands === null) { 106569 return null; 106570 } 106571 106572 return this.router.createUrlTree(this.commands, { 106573 // If the `relativeTo` input is not defined, we want to use `this.route` by default. 106574 // Otherwise, we should use the value provided by the user in the input. 106575 relativeTo: this.relativeTo !== undefined ? this.relativeTo : this.route, 106576 queryParams: this.queryParams, 106577 fragment: this.fragment, 106578 queryParamsHandling: this.queryParamsHandling, 106579 preserveFragment: this.preserveFragment 106580 }); 106581 } 106582 106583} 106584 106585RouterLinkWithHref.ɵfac = function RouterLinkWithHref_Factory(t) { 106586 return new (t || RouterLinkWithHref)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](Router), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](ActivatedRoute), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_common__WEBPACK_IMPORTED_MODULE_33__.LocationStrategy)); 106587}; 106588 106589RouterLinkWithHref.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 106590 type: RouterLinkWithHref, 106591 selectors: [["a", "routerLink", ""], ["area", "routerLink", ""]], 106592 hostVars: 2, 106593 hostBindings: function RouterLinkWithHref_HostBindings(rf, ctx) { 106594 if (rf & 1) { 106595 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵlistener"]("click", function RouterLinkWithHref_click_HostBindingHandler($event) { 106596 return ctx.onClick($event.button, $event.ctrlKey, $event.shiftKey, $event.altKey, $event.metaKey); 106597 }); 106598 } 106599 106600 if (rf & 2) { 106601 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵattribute"]("target", ctx.target)("href", ctx.href, _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵsanitizeUrl"]); 106602 } 106603 }, 106604 inputs: { 106605 target: "target", 106606 queryParams: "queryParams", 106607 fragment: "fragment", 106608 queryParamsHandling: "queryParamsHandling", 106609 state: "state", 106610 relativeTo: "relativeTo", 106611 preserveFragment: "preserveFragment", 106612 skipLocationChange: "skipLocationChange", 106613 replaceUrl: "replaceUrl", 106614 routerLink: "routerLink" 106615 }, 106616 standalone: true, 106617 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]] 106618}); 106619 106620(function () { 106621 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterLinkWithHref, [{ 106622 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 106623 args: [{ 106624 selector: 'a[routerLink],area[routerLink]', 106625 standalone: true 106626 }] 106627 }], function () { 106628 return [{ 106629 type: Router 106630 }, { 106631 type: ActivatedRoute 106632 }, { 106633 type: _angular_common__WEBPACK_IMPORTED_MODULE_33__.LocationStrategy 106634 }]; 106635 }, { 106636 target: [{ 106637 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostBinding, 106638 args: ['attr.target'] 106639 }, { 106640 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106641 }], 106642 queryParams: [{ 106643 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106644 }], 106645 fragment: [{ 106646 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106647 }], 106648 queryParamsHandling: [{ 106649 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106650 }], 106651 state: [{ 106652 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106653 }], 106654 relativeTo: [{ 106655 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106656 }], 106657 href: [{ 106658 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostBinding, 106659 args: ['attr.href'] 106660 }], 106661 preserveFragment: [{ 106662 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106663 }], 106664 skipLocationChange: [{ 106665 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106666 }], 106667 replaceUrl: [{ 106668 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106669 }], 106670 routerLink: [{ 106671 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106672 }], 106673 onClick: [{ 106674 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.HostListener, 106675 args: ['click', ['$event.button', '$event.ctrlKey', '$event.shiftKey', '$event.altKey', '$event.metaKey']] 106676 }] 106677 }); 106678})(); 106679/** 106680 * @license 106681 * Copyright Google LLC All Rights Reserved. 106682 * 106683 * Use of this source code is governed by an MIT-style license that can be 106684 * found in the LICENSE file at https://angular.io/license 106685 */ 106686 106687/** 106688 * 106689 * @description 106690 * 106691 * Tracks whether the linked route of an element is currently active, and allows you 106692 * to specify one or more CSS classes to add to the element when the linked route 106693 * is active. 106694 * 106695 * Use this directive to create a visual distinction for elements associated with an active route. 106696 * For example, the following code highlights the word "Bob" when the router 106697 * activates the associated route: 106698 * 106699 * ``` 106700 * <a routerLink="/user/bob" routerLinkActive="active-link">Bob</a> 106701 * ``` 106702 * 106703 * Whenever the URL is either '/user' or '/user/bob', the "active-link" class is
106704 * added to the anchor tag. If the URL changes, the class is removed. 106705 * 106706 * You can set more than one class using a space-separated string or an array. 106707 * For example: 106708 * 106709 * ``` 106710 * <a routerLink="/user/bob" routerLinkActive="class1 class2">Bob</a> 106711 * <a routerLink="/user/bob" [routerLinkActive]="['class1', 'class2']">Bob</a> 106712 * ``` 106713 * 106714 * To add the classes only when the URL matches the link exactly, add the option `exact: true`: 106715 * 106716 * ``` 106717 * <a routerLink="/user/bob" routerLinkActive="active-link" [routerLinkActiveOptions]="{exact: 106718 * true}">Bob</a> 106719 * ``` 106720 * 106721 * To directly check the `isActive` status of the link, assign the `RouterLinkActive` 106722 * instance to a template variable. 106723 * For example, the following checks the status without assigning any CSS classes: 106724 * 106725 * ``` 106726 * <a routerLink="/user/bob" routerLinkActive #rla="routerLinkActive"> 106727 * Bob {{ rla.isActive ? '(already open)' : ''}} 106728 * </a> 106729 * ``` 106730 * 106731 * You can apply the `RouterLinkActive` directive to an ancestor of linked elements. 106732 * For example, the following sets the active-link class on the `<div>` parent tag 106733 * when the URL is either '/user/jim' or '/user/bob'. 106734 * 106735 * ``` 106736 * <div routerLinkActive="active-link" [routerLinkActiveOptions]="{exact: true}"> 106737 * <a routerLink="/user/jim">Jim</a> 106738 * <a routerLink="/user/bob">Bob</a> 106739 * </div> 106740 * ``` 106741 * 106742 * The `RouterLinkActive` directive can also be used to set the aria-current attribute 106743 * to provide an alternative distinction for active elements to visually impaired users. 106744 * 106745 * For example, the following code adds the 'active' class to the Home Page link when it is 106746 * indeed active and in such case also sets its aria-current attribute to 'page': 106747 * 106748 * ``` 106749 * <a routerLink="/" routerLinkActive="active" ariaCurrentWhenActive="page">Home Page</a> 106750 * ``` 106751 * 106752 * @ngModule RouterModule 106753 * 106754 * @publicApi 106755 */ 106756 106757 106758class RouterLinkActive { 106759 constructor(router, element, renderer, cdr, link, linkWithHref) { 106760 this.router = router; 106761 this.element = element; 106762 this.renderer = renderer; 106763 this.cdr = cdr; 106764 this.link = link; 106765 this.linkWithHref = linkWithHref; 106766 this.classes = []; 106767 this.isActive = false; 106768 /** 106769 * Options to configure how to determine if the router link is active. 106770 * 106771 * These options are passed to the `Router.isActive()` function. 106772 * 106773 * @see Router.isActive 106774 */ 106775 106776 this.routerLinkActiveOptions = { 106777 exact: false 106778 }; 106779 /** 106780 * 106781 * You can use the output `isActiveChange` to get notified each time the link becomes 106782 * active or inactive. 106783 * 106784 * Emits: 106785 * true -> Route is active 106786 * false -> Route is inactive 106787 * 106788 * ``` 106789 * <a 106790 * routerLink="/user/bob" 106791 * routerLinkActive="active-link" 106792 * (isActiveChange)="this.onRouterLinkActive($event)">Bob</a> 106793 * ``` 106794 */ 106795 106796 this.isActiveChange = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); 106797 this.routerEventsSubscription = router.events.subscribe(s => { 106798 if (s instanceof NavigationEnd) { 106799 this.update(); 106800 } 106801 }); 106802 } 106803 /** @nodoc */ 106804 106805 106806 ngAfterContentInit() { 106807 // `of(null)` is used to force subscribe body to execute once immediately (like `startWith`). 106808 (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(this.links.changes, this.linksWithHrefs.changes, (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null)).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_34__.mergeAll)()).subscribe(_ => { 106809 this.update(); 106810 this.subscribeToEachLinkOnChanges(); 106811 }); 106812 } 106813 106814 subscribeToEachLinkOnChanges() { 106815 this.linkInputChangesSubscription?.unsubscribe(); 106816 const allLinkChanges = [...this.links.toArray(), ...this.linksWithHrefs.toArray(), this.link, this.linkWithHref].filter(link => !!link).map(link => link.onChanges); 106817 this.linkInputChangesSubscription = (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(allLinkChanges).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_34__.mergeAll)()).subscribe(link => { 106818 if (this.isActive !== this.isLinkActive(this.router)(link)) { 106819 this.update(); 106820 } 106821 }); 106822 } 106823 106824 set routerLinkActive(data) { 106825 const classes = Array.isArray(data) ? data : data.split(' '); 106826 this.classes = classes.filter(c => !!c); 106827 } 106828 /** @nodoc */ 106829 106830 106831 ngOnChanges(changes) { 106832 this.update(); 106833 } 106834 /** @nodoc */ 106835 106836 106837 ngOnDestroy() { 106838 this.routerEventsSubscription.unsubscribe(); 106839 this.linkInputChangesSubscription?.unsubscribe(); 106840 } 106841 106842 update() { 106843 if (!this.links || !this.linksWithHrefs || !this.router.navigated) return; 106844 Promise.resolve().then(() => { 106845 const hasActiveLinks = this.hasActiveLinks(); 106846 106847 if (this.isActive !== hasActiveLinks) { 106848 this.isActive = hasActiveLinks; 106849 this.cdr.markForCheck();
106850 this.classes.forEach(c => { 106851 if (hasActiveLinks) { 106852 this.renderer.addClass(this.element.nativeElement, c); 106853 } else { 106854 this.renderer.removeClass(this.element.nativeElement, c); 106855 } 106856 }); 106857 106858 if (hasActiveLinks && this.ariaCurrentWhenActive !== undefined) { 106859 this.renderer.setAttribute(this.element.nativeElement, 'aria-current', this.ariaCurrentWhenActive.toString()); 106860 } else { 106861 this.renderer.removeAttribute(this.element.nativeElement, 'aria-current'); 106862 } // Emit on isActiveChange after classes are updated 106863 106864 106865 this.isActiveChange.emit(hasActiveLinks); 106866 } 106867 }); 106868 } 106869 106870 isLinkActive(router) { 106871 const options = isActiveMatchOptions(this.routerLinkActiveOptions) ? this.routerLinkActiveOptions : // While the types should disallow `undefined` here, it's possible without strict inputs 106872 this.routerLinkActiveOptions.exact || false; 106873 return link => link.urlTree ? router.isActive(link.urlTree, options) : false; 106874 } 106875 106876 hasActiveLinks() { 106877 const isActiveCheckFn = this.isLinkActive(this.router); 106878 return this.link && isActiveCheckFn(this.link) || this.linkWithHref && isActiveCheckFn(this.linkWithHref) || this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn); 106879 } 106880 106881} 106882 106883RouterLinkActive.ɵfac = function RouterLinkActive_Factory(t) { 106884 return new (t || RouterLinkActive)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](Router), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](RouterLink, 8), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](RouterLinkWithHref, 8)); 106885}; 106886 106887RouterLinkActive.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ 106888 type: RouterLinkActive, 106889 selectors: [["", "routerLinkActive", ""]], 106890 contentQueries: function RouterLinkActive_ContentQueries(rf, ctx, dirIndex) { 106891 if (rf & 1) { 106892 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵcontentQuery"](dirIndex, RouterLink, 5); 106893 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵcontentQuery"](dirIndex, RouterLinkWithHref, 5); 106894 } 106895 106896 if (rf & 2) { 106897 let _t; 106898 106899 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵqueryRefresh"](_t = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵloadQuery"]()) && (ctx.links = _t); 106900 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵqueryRefresh"](_t = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵloadQuery"]()) && (ctx.linksWithHrefs = _t); 106901 } 106902 }, 106903 inputs: { 106904 routerLinkActiveOptions: "routerLinkActiveOptions", 106905 ariaCurrentWhenActive: "ariaCurrentWhenActive", 106906 routerLinkActive: "routerLinkActive" 106907 }, 106908 outputs: { 106909 isActiveChange: "isActiveChange" 106910 }, 106911 exportAs: ["routerLinkActive"], 106912 standalone: true, 106913 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]] 106914}); 106915 106916(function () { 106917 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterLinkActive, [{ 106918 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Directive, 106919 args: [{ 106920 selector: '[routerLinkActive]', 106921 exportAs: 'routerLinkActive', 106922 standalone: true 106923 }] 106924 }], function () { 106925 return [{ 106926 type: Router 106927 }, { 106928 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef 106929 }, { 106930 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2 106931 }, { 106932 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef 106933 }, { 106934 type: RouterLink, 106935 decorators: [{ 106936 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 106937 }] 106938 }, { 106939 type: RouterLinkWithHref, 106940 decorators: [{ 106941 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 106942 }] 106943 }]; 106944 }, { 106945 links: [{ 106946 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ContentChildren, 106947 args: [RouterLink, { 106948 descendants: true 106949 }] 106950 }], 106951 linksWithHrefs: [{ 106952 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ContentChildren, 106953 args: [RouterLinkWithHref, { 106954 descendants: true 106955 }] 106956 }], 106957 routerLinkActiveOptions: [{ 106958 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106959 }], 106960 ariaCurrentWhenActive: [{ 106961 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106962 }], 106963 isActiveChange: [{ 106964 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Output 106965 }], 106966 routerLinkActive: [{ 106967 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 106968 }] 106969 }); 106970})(); 106971/** 106972 * Use instead of `'paths' in options` to be compatible with property renaming 106973 */ 106974 106975 106976function isActiveMatchOptions(options) { 106977 return !!options.paths; 106978} 106979/** 106980 * @license 106981 * Copyright Google LLC All Rights Reserved. 106982 * 106983 * Use of this source code is governed by an MIT-style license that can be 106984 * found in the LICENSE file at https://angular.io/license 106985 */ 106986 106987/** 106988 * @description 106989 * 106990 * Provides a preloading strategy. 106991 * 106992 * @publicApi 106993 */ 106994 106995 106996class PreloadingStrategy {}
106997/** 106998 * @description 106999 * 107000 * Provides a preloading strategy that preloads all modules as quickly as possible. 107001 * 107002 * ``` 107003 * RouterModule.forRoot(ROUTES, {preloadingStrategy: PreloadAllModules}) 107004 * ``` 107005 * 107006 * @publicApi 107007 */ 107008 107009 107010class PreloadAllModules { 107011 preload(route, fn) { 107012 return fn().pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_19__.catchError)(() => (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null))); 107013 } 107014 107015} 107016 107017PreloadAllModules.ɵfac = function PreloadAllModules_Factory(t) { 107018 return new (t || PreloadAllModules)(); 107019}; 107020 107021PreloadAllModules.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 107022 token: PreloadAllModules, 107023 factory: PreloadAllModules.ɵfac, 107024 providedIn: 'root' 107025}); 107026 107027(function () { 107028 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](PreloadAllModules, [{ 107029 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 107030 args: [{ 107031 providedIn: 'root' 107032 }] 107033 }], null, null); 107034})(); 107035/** 107036 * @description 107037 * 107038 * Provides a preloading strategy that does not preload any modules. 107039 * 107040 * This strategy is enabled by default. 107041 * 107042 * @publicApi 107043 */ 107044 107045 107046class NoPreloading { 107047 preload(route, fn) { 107048 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null); 107049 } 107050 107051} 107052 107053NoPreloading.ɵfac = function NoPreloading_Factory(t) { 107054 return new (t || NoPreloading)(); 107055}; 107056 107057NoPreloading.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 107058 token: NoPreloading, 107059 factory: NoPreloading.ɵfac, 107060 providedIn: 'root' 107061}); 107062 107063(function () { 107064 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NoPreloading, [{ 107065 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 107066 args: [{ 107067 providedIn: 'root' 107068 }] 107069 }], null, null); 107070})(); 107071/** 107072 * The preloader optimistically loads all router configurations to 107073 * make navigations into lazily-loaded sections of the application faster. 107074 * 107075 * The preloader runs in the background. When the router bootstraps, the preloader 107076 * starts listening to all navigation events. After every such event, the preloader 107077 * will check if any configurations can be loaded lazily. 107078 * 107079 * If a route is protected by `canLoad` guards, the preloaded will not load it. 107080 * 107081 * @publicApi 107082 */ 107083 107084 107085class RouterPreloader { 107086 constructor(router, compiler, injector, preloadingStrategy, loader) { 107087 this.router = router; 107088 this.injector = injector; 107089 this.preloadingStrategy = preloadingStrategy; 107090 this.loader = loader; 107091 } 107092 107093 setUpPreloading() { 107094 this.subscription = this.router.events.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.filter)(e => e instanceof NavigationEnd), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_13__.concatMap)(() => this.preload())).subscribe(() => {}); 107095 } 107096 107097 preload() { 107098 return this.processRoutes(this.injector, this.router.config); 107099 } 107100 /** @nodoc */ 107101 107102 107103 ngOnDestroy() { 107104 if (this.subscription) { 107105 this.subscription.unsubscribe(); 107106 } 107107 } 107108 107109 processRoutes(injector, routes) { 107110 const res = []; 107111 107112 for (const route of routes) { 107113 if (route.providers && !route._injector) { 107114 route._injector = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.createEnvironmentInjector)(route.providers, injector, `Route: ${route.path}`); 107115 } 107116 107117 const injectorForCurrentRoute = route._injector ?? injector; 107118 const injectorForChildren = route._loadedInjector ?? injectorForCurrentRoute; // Note that `canLoad` is only checked as a condition that prevents `loadChildren` and not 107119 // `loadComponent`. `canLoad` guards only block loading of child routes by design. This 107120 // happens as a consequence of needing to descend into children for route matching immediately 107121 // while component loading is deferred until route activation. Because `canLoad` guards can 107122 // have side effects, we cannot execute them here so we instead skip preloading altogether 107123 // when present. Lastly, it remains to be decided whether `canLoad` should behave this way 107124 // at all. Code splitting and lazy loading is separate from client-side authorization checks 107125 // and should not be used as a security measure to prevent loading of code. 107126 107127 if (route.loadChildren && !route._loadedRoutes && route.canLoad === undefined || route.loadComponent && !route._loadedComponent) { 107128 res.push(this.preloadConfig(injectorForCurrentRoute, route)); 107129 } else if (route.children || route._loadedRoutes) { 107130 res.push(this.processRoutes(injectorForChildren, route.children ?? route._loadedRoutes)); 107131 } 107132 } 107133 107134 return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)(res).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_34__.mergeAll)()); 107135 } 107136 107137 preloadConfig(injector, route) { 107138 return this.preloadingStrategy.preload(route, () => { 107139 let loadedChildren$; 107140 107141 if (route.loadChildren && route.canLoad === undefined) { 107142 loadedChildren$ = this.loader.loadChildren(injector, route); 107143 } else { 107144 loadedChildren$ = (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(null); 107145 } 107146 107147 const recursiveLoadChildren$ = loadedChildren$.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_11__.mergeMap)(config => { 107148 if (config === null) { 107149 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(void 0); 107150 } 107151 107152 route._loadedRoutes = config.routes; 107153 route._loadedInjector = config.injector; // If the loaded config was a module, use that as the module/module injector going 107154 // forward. Otherwise, continue using the current module/module injector. 107155 107156 return this.processRoutes(config.injector ?? injector, config.routes); 107157 })); 107158 107159 if (route.loadComponent && !route._loadedComponent) { 107160 const loadComponent$ = this.loader.loadComponent(route); 107161 return (0,rxjs__WEBPACK_IMPORTED_MODULE_1__.from)([recursiveLoadChildren$, loadComponent$]).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_34__.mergeAll)()); 107162 } else { 107163 return recursiveLoadChildren$; 107164 } 107165 }); 107166 } 107167 107168} 107169 107170RouterPreloader.ɵfac = function RouterPreloader_Factory(t) { 107171 return new (t || RouterPreloader)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](Router), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Compiler), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.EnvironmentInjector), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](PreloadingStrategy), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](RouterConfigLoader)); 107172}; 107173 107174RouterPreloader.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 107175 token: RouterPreloader, 107176 factory: RouterPreloader.ɵfac, 107177 providedIn: 'root' 107178}); 107179 107180(function () { 107181 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterPreloader, [{ 107182 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable, 107183 args: [{ 107184 providedIn: 'root' 107185 }] 107186 }], function () { 107187 return [{ 107188 type: Router 107189 }, {
107190 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Compiler 107191 }, { 107192 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.EnvironmentInjector 107193 }, { 107194 type: PreloadingStrategy 107195 }, { 107196 type: RouterConfigLoader 107197 }]; 107198 }, null); 107199})(); 107200/** 107201 * @license 107202 * Copyright Google LLC All Rights Reserved. 107203 * 107204 * Use of this source code is governed by an MIT-style license that can be 107205 * found in the LICENSE file at https://angular.io/license 107206 */ 107207 107208 107209const ROUTER_SCROLLER = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken(''); 107210 107211class RouterScroller { 107212 constructor(router, 107213 /** @docsNotRequired */ 107214 viewportScroller, options = {}) { 107215 this.router = router; 107216 this.viewportScroller = viewportScroller; 107217 this.options = options; 107218 this.lastId = 0; 107219 this.lastSource = 'imperative'; 107220 this.restoredId = 0; 107221 this.store = {}; // Default both options to 'disabled' 107222 107223 options.scrollPositionRestoration = options.scrollPositionRestoration || 'disabled'; 107224 options.anchorScrolling = options.anchorScrolling || 'disabled'; 107225 } 107226 107227 init() { 107228 // we want to disable the automatic scrolling because having two places 107229 // responsible for scrolling results race conditions, especially given 107230 // that browser don't implement this behavior consistently 107231 if (this.options.scrollPositionRestoration !== 'disabled') { 107232 this.viewportScroller.setHistoryScrollRestoration('manual'); 107233 } 107234 107235 this.routerEventsSubscription = this.createScrollEvents(); 107236 this.scrollEventsSubscription = this.consumeScrollEvents(); 107237 } 107238 107239 createScrollEvents() { 107240 return this.router.events.subscribe(e => { 107241 if (e instanceof NavigationStart) { 107242 // store the scroll position of the current stable navigations. 107243 this.store[this.lastId] = this.viewportScroller.getScrollPosition(); 107244 this.lastSource = e.navigationTrigger; 107245 this.restoredId = e.restoredState ? e.restoredState.navigationId : 0; 107246 } else if (e instanceof NavigationEnd) { 107247 this.lastId = e.id; 107248 this.scheduleScrollEvent(e, this.router.parseUrl(e.urlAfterRedirects).fragment); 107249 } 107250 }); 107251 } 107252 107253 consumeScrollEvents() { 107254 return this.router.events.subscribe(e => { 107255 if (!(e instanceof Scroll)) return; // a popstate event. The pop state event will always ignore anchor scrolling. 107256 107257 if (e.position) { 107258 if (this.options.scrollPositionRestoration === 'top') { 107259 this.viewportScroller.scrollToPosition([0, 0]); 107260 } else if (this.options.scrollPositionRestoration === 'enabled') { 107261 this.viewportScroller.scrollToPosition(e.position); 107262 } // imperative navigation "forward" 107263 107264 } else { 107265 if (e.anchor && this.options.anchorScrolling === 'enabled') { 107266 this.viewportScroller.scrollToAnchor(e.anchor); 107267 } else if (this.options.scrollPositionRestoration !== 'disabled') { 107268 this.viewportScroller.scrollToPosition([0, 0]); 107269 } 107270 } 107271 }); 107272 } 107273 107274 scheduleScrollEvent(routerEvent, anchor) { 107275 this.router.triggerEvent(new Scroll(routerEvent, this.lastSource === 'popstate' ? this.store[this.restoredId] : null, anchor)); 107276 } 107277 /** @nodoc */ 107278 107279 107280 ngOnDestroy() { 107281 if (this.routerEventsSubscription) { 107282 this.routerEventsSubscription.unsubscribe(); 107283 } 107284 107285 if (this.scrollEventsSubscription) { 107286 this.scrollEventsSubscription.unsubscribe(); 107287 } 107288 } 107289 107290} 107291 107292RouterScroller.ɵfac = function RouterScroller_Factory(t) { 107293 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinvalidFactory"](); 107294}; 107295 107296RouterScroller.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 107297 token: RouterScroller, 107298 factory: RouterScroller.ɵfac 107299}); 107300 107301(function () { 107302 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterScroller, [{ 107303 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable 107304 }], function () { 107305 return [{ 107306 type: Router 107307 }, { 107308 type: _angular_common__WEBPACK_IMPORTED_MODULE_33__.ViewportScroller 107309 }, { 107310 type: undefined 107311 }]; 107312 }, null); 107313})(); 107314/** 107315 * @license 107316 * Copyright Google LLC All Rights Reserved. 107317 * 107318 * Use of this source code is governed by an MIT-style license that can be 107319 * found in the LICENSE file at https://angular.io/license 107320 */ 107321 107322 107323const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || ngDevMode; 107324/** 107325 * Sets up providers necessary to enable `Router` functionality for the application. 107326 * Allows to configure a set of routes as well as extra features that should be enabled. 107327 * 107328 * @usageNotes 107329 * 107330 * Basic example of how you can add a Router to your application: 107331 * ``` 107332 * const appRoutes: Routes = []; 107333 * bootstrapApplication(AppComponent, {
107334 * providers: [provideRouter(appRoutes)] 107335 * }); 107336 * ``` 107337 * 107338 * You can also enable optional features in the Router by adding functions from the `RouterFeatures` 107339 * type: 107340 * ``` 107341 * const appRoutes: Routes = []; 107342 * bootstrapApplication(AppComponent, 107343 * { 107344 * providers: [ 107345 * provideRouter(appRoutes, 107346 * withDebugTracing(), 107347 * withRouterConfig({paramsInheritanceStrategy: 'always'})) 107348 * ] 107349 * } 107350 * ); 107351 * ``` 107352 * 107353 * @see `RouterFeatures` 107354 * 107355 * @publicApi 107356 * @developerPreview 107357 * @param routes A set of `Route`s to use for the application routing table. 107358 * @param features Optional features to configure additional router behaviors. 107359 * @returns A set of providers to setup a Router. 107360 */ 107361 107362function provideRouter(routes, ...features) { 107363 return [provideRoutes(routes), { 107364 provide: ActivatedRoute, 107365 useFactory: rootRoute, 107366 deps: [Router] 107367 }, { 107368 provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.APP_BOOTSTRAP_LISTENER, 107369 multi: true, 107370 useFactory: getBootstrapListener 107371 }, features.map(feature => feature.ɵproviders) // TODO: All options used by the `assignExtraOptionsToRouter` factory need to be reviewed for 107372 // how we want them to be configured. This API doesn't currently have a way to configure them 107373 // and we should decide what the _best_ way to do that is rather than just sticking with the 107374 // status quo of how it's done today. 107375 ]; 107376} 107377 107378function rootRoute(router) { 107379 return router.routerState.root; 107380} 107381/** 107382 * Helper function to create an object that represents a Router feature. 107383 */ 107384 107385 107386function routerFeature(kind, providers) { 107387 return { 107388 ɵkind: kind, 107389 ɵproviders: providers 107390 }; 107391} 107392/** 107393 * Registers a [DI provider](guide/glossary#provider) for a set of routes. 107394 * @param routes The route configuration to provide. 107395 * 107396 * @usageNotes 107397 * 107398 * ``` 107399 * @NgModule({ 107400 * providers: [provideRoutes(ROUTES)] 107401 * }) 107402 * class LazyLoadedChildModule {} 107403 * ``` 107404 * 107405 * @publicApi 107406 */ 107407 107408 107409function provideRoutes(routes) { 107410 return [{ 107411 provide: ROUTES, 107412 multi: true, 107413 useValue: routes 107414 }]; 107415} 107416/** 107417 * Enables customizable scrolling behavior for router navigations. 107418 * 107419 * @usageNotes 107420 * 107421 * Basic example of how you can enable scrolling feature: 107422 * ``` 107423 * const appRoutes: Routes = []; 107424 * bootstrapApplication(AppComponent, 107425 * { 107426 * providers: [ 107427 * provideRouter(appRoutes, withInMemoryScrolling()) 107428 * ] 107429 * } 107430 * ); 107431 * ``` 107432 * 107433 * @see `provideRouter` 107434 * @see `ViewportScroller` 107435 * 107436 * @publicApi 107437 * @developerPreview 107438 * @param options Set of configuration parameters to customize scrolling behavior, see 107439 * `InMemoryScrollingOptions` for additional information. 107440 * @returns A set of providers for use with `provideRouter`. 107441 */ 107442 107443 107444function withInMemoryScrolling(options = {}) { 107445 const providers = [{ 107446 provide: ROUTER_SCROLLER, 107447 useFactory: () => { 107448 const router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(Router); 107449 const viewportScroller = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_33__.ViewportScroller); 107450 return new RouterScroller(router, viewportScroller, options); 107451 } 107452 }]; 107453 return routerFeature(4 107454 /* RouterFeatureKind.InMemoryScrollingFeature */ 107455 , providers); 107456} 107457 107458function getBootstrapListener() { 107459 const injector = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector); 107460 return bootstrappedComponentRef => { 107461 const ref = injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__.ApplicationRef); 107462 107463 if (bootstrappedComponentRef !== ref.components[0]) { 107464 return; 107465 } 107466 107467 const router = injector.get(Router); 107468 const bootstrapDone = injector.get(BOOTSTRAP_DONE); 107469 107470 if (injector.get(INITIAL_NAVIGATION) === 1 107471 /* InitialNavigation.EnabledNonBlocking */ 107472 ) { 107473 router.initialNavigation(); 107474 } 107475 107476 injector.get(ROUTER_PRELOADER, null, _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectFlags.Optional)?.setUpPreloading(); 107477 injector.get(ROUTER_SCROLLER, null, _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectFlags.Optional)?.init(); 107478 router.resetRootComponentType(ref.componentTypes[0]); 107479 bootstrapDone.next(); 107480 bootstrapDone.complete(); 107481 }; 107482} 107483/** 107484 * A subject used to indicate that the bootstrapping phase is done. When initial navigation is 107485 * `enabledBlocking`, the first navigation waits until bootstrapping is finished before continuing 107486 * to the activation phase. 107487 */ 107488 107489 107490const BOOTSTRAP_DONE = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken(NG_DEV_MODE$1 ? 'bootstrap done indicator' : '', { 107491 factory: () => { 107492 return new rxjs__WEBPACK_IMPORTED_MODULE_31__.Subject(); 107493 } 107494}); 107495const INITIAL_NAVIGATION = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken(NG_DEV_MODE$1 ? 'initial navigation' : '', { 107496 providedIn: 'root', 107497 factory: () => 1 107498 /* InitialNavigation.EnabledNonBlocking */ 107499 107500}); 107501/** 107502 * Configures initial navigation to start before the root component is created. 107503 * 107504 * The bootstrap is blocked until the initial navigation is complete. This value is required for 107505 * [server-side rendering](guide/universal) to work. 107506 * 107507 * @usageNotes 107508 * 107509 * Basic example of how you can enable this navigation behavior: 107510 * ``` 107511 * const appRoutes: Routes = []; 107512 * bootstrapApplication(AppComponent, 107513 * {
107514 * providers: [ 107515 * provideRouter(appRoutes, withEnabledBlockingInitialNavigation()) 107516 * ] 107517 * } 107518 * ); 107519 * ``` 107520 * 107521 * @see `provideRouter` 107522 * 107523 * @publicApi 107524 * @developerPreview 107525 * @returns A set of providers for use with `provideRouter`. 107526 */ 107527 107528function withEnabledBlockingInitialNavigation() { 107529 const providers = [{ 107530 provide: INITIAL_NAVIGATION, 107531 useValue: 0 107532 /* InitialNavigation.EnabledBlocking */ 107533 107534 }, { 107535 provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.APP_INITIALIZER, 107536 multi: true, 107537 deps: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.Injector], 107538 useFactory: injector => { 107539 const locationInitialized = injector.get(_angular_common__WEBPACK_IMPORTED_MODULE_33__.LOCATION_INITIALIZED, Promise.resolve()); 107540 let initNavigation = false; 107541 /** 107542 * Performs the given action once the router finishes its next/current navigation. 107543 * 107544 * If the navigation is canceled or errors without a redirect, the navigation is considered 107545 * complete. If the `NavigationEnd` event emits, the navigation is also considered complete. 107546 */ 107547 107548 function afterNextNavigation(action) { 107549 const router = injector.get(Router); 107550 router.events.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.filter)(e => e instanceof NavigationEnd || e instanceof NavigationCancel || e instanceof NavigationError), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.map)(e => { 107551 if (e instanceof NavigationEnd) { 107552 // Navigation assumed to succeed if we get `ActivationStart` 107553 return true; 107554 } 107555 107556 const redirecting = e instanceof NavigationCancel ? e.code === 0 107557 /* NavigationCancellationCode.Redirect */ 107558 || e.code === 1 107559 /* NavigationCancellationCode.SupersededByNewNavigation */ 107560 : false; 107561 return redirecting ? null : false; 107562 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_10__.filter)(result => result !== null), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.take)(1)).subscribe(() => { 107563 action(); 107564 }); 107565 } 107566 107567 return () => { 107568 return locationInitialized.then(() => { 107569 return new Promise(resolve => { 107570 const router = injector.get(Router); 107571 const bootstrapDone = injector.get(BOOTSTRAP_DONE); 107572 afterNextNavigation(() => { 107573 // Unblock APP_INITIALIZER in case the initial navigation was canceled or errored 107574 // without a redirect. 107575 resolve(true); 107576 initNavigation = true; 107577 }); 107578 107579 router.afterPreactivation = () => { 107580 // Unblock APP_INITIALIZER once we get to `afterPreactivation`. At this point, we 107581 // assume activation will complete successfully (even though this is not 107582 // guaranteed). 107583 resolve(true); // only the initial navigation should be delayed until bootstrapping is done. 107584 107585 if (!initNavigation) { 107586 return bootstrapDone.closed ? (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(void 0) : bootstrapDone; // subsequent navigations should not be delayed 107587 } else { 107588 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(void 0); 107589 } 107590 }; 107591 107592 router.initialNavigation(); 107593 }); 107594 }); 107595 }; 107596 } 107597 }]; 107598 return routerFeature(2 107599 /* RouterFeatureKind.EnabledBlockingInitialNavigationFeature */ 107600 , providers); 107601} 107602/** 107603 * Disables initial navigation. 107604 * 107605 * Use if there is a reason to have more control over when the router starts its initial navigation 107606 * due to some complex initialization logic. 107607 * 107608 * @usageNotes 107609 * 107610 * Basic example of how you can disable initial navigation: 107611 * ``` 107612 * const appRoutes: Routes = []; 107613 * bootstrapApplication(AppComponent, 107614 * { 107615 * providers: [ 107616 * provideRouter(appRoutes, withDisabledInitialNavigation()) 107617 * ] 107618 * } 107619 * ); 107620 * ``` 107621 * 107622 * @see `provideRouter` 107623 * 107624 * @returns A set of providers for use with `provideRouter`. 107625 * 107626 * @publicApi 107627 * @developerPreview 107628 */ 107629 107630 107631function withDisabledInitialNavigation() { 107632 const providers = [{ 107633 provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.APP_INITIALIZER, 107634 multi: true, 107635 useFactory: () => { 107636 const router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(Router); 107637 return () => { 107638 router.setUpLocationChangeListener(); 107639 }; 107640 } 107641 }, { 107642 provide: INITIAL_NAVIGATION, 107643 useValue: 2 107644 /* InitialNavigation.Disabled */ 107645 107646 }]; 107647 return routerFeature(3 107648 /* RouterFeatureKind.DisabledInitialNavigationFeature */ 107649 , providers); 107650} 107651/** 107652 * Enables logging of all internal navigation events to the console. 107653 * Extra logging might be useful for debugging purposes to inspect Router event sequence. 107654 * 107655 * @usageNotes 107656 * 107657 * Basic example of how you can enable debug tracing: 107658 * ``` 107659 * const appRoutes: Routes = []; 107660 * bootstrapApplication(AppComponent, 107661 * {
107662 * providers: [ 107663 * provideRouter(appRoutes, withDebugTracing()) 107664 * ] 107665 * } 107666 * ); 107667 * ``` 107668 * 107669 * @see `provideRouter` 107670 * 107671 * @returns A set of providers for use with `provideRouter`. 107672 * 107673 * @publicApi 107674 * @developerPreview 107675 */ 107676 107677 107678function withDebugTracing() { 107679 let providers = []; 107680 107681 if (NG_DEV_MODE$1) { 107682 providers = [{ 107683 provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ENVIRONMENT_INITIALIZER, 107684 multi: true, 107685 useFactory: () => { 107686 const router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(Router); 107687 return () => router.events.subscribe(e => { 107688 // tslint:disable:no-console 107689 console.group?.(`Router Event: ${e.constructor.name}`); 107690 console.log(stringifyEvent(e)); 107691 console.log(e); 107692 console.groupEnd?.(); // tslint:enable:no-console 107693 }); 107694 } 107695 }]; 107696 } else { 107697 providers = []; 107698 } 107699 107700 return routerFeature(1 107701 /* RouterFeatureKind.DebugTracingFeature */ 107702 , providers); 107703} 107704 107705const ROUTER_PRELOADER = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken(NG_DEV_MODE$1 ? 'router preloader' : ''); 107706/** 107707 * Allows to configure a preloading strategy to use. The strategy is configured by providing a 107708 * reference to a class that implements a `PreloadingStrategy`. 107709 * 107710 * @usageNotes 107711 * 107712 * Basic example of how you can configure preloading: 107713 * ``` 107714 * const appRoutes: Routes = []; 107715 * bootstrapApplication(AppComponent, 107716 * { 107717 * providers: [ 107718 * provideRouter(appRoutes, withPreloading(PreloadAllModules)) 107719 * ] 107720 * } 107721 * ); 107722 * ``` 107723 * 107724 * @see `provideRouter` 107725 * 107726 * @param preloadingStrategy A reference to a class that implements a `PreloadingStrategy` that 107727 * should be used. 107728 * @returns A set of providers for use with `provideRouter`. 107729 * 107730 * @publicApi 107731 * @developerPreview 107732 */ 107733 107734function withPreloading(preloadingStrategy) { 107735 const providers = [{ 107736 provide: ROUTER_PRELOADER, 107737 useExisting: RouterPreloader 107738 }, { 107739 provide: PreloadingStrategy, 107740 useExisting: preloadingStrategy 107741 }]; 107742 return routerFeature(0 107743 /* RouterFeatureKind.PreloadingFeature */ 107744 , providers); 107745} 107746/** 107747 * Allows to provide extra parameters to configure Router. 107748 * 107749 * @usageNotes 107750 * 107751 * Basic example of how you can provide extra configuration options: 107752 * ``` 107753 * const appRoutes: Routes = []; 107754 * bootstrapApplication(AppComponent, 107755 * { 107756 * providers: [ 107757 * provideRouter(appRoutes, withRouterConfig({ 107758 * onSameUrlNavigation: 'reload' 107759 * })) 107760 * ] 107761 * } 107762 * ); 107763 * ``` 107764 * 107765 * @see `provideRouter` 107766 * 107767 * @param options A set of parameters to configure Router, see `RouterConfigOptions` for 107768 * additional information. 107769 * @returns A set of providers for use with `provideRouter`. 107770 * 107771 * @publicApi 107772 * @developerPreview 107773 */ 107774 107775 107776function withRouterConfig(options) { 107777 const providers = [{ 107778 provide: ROUTER_CONFIGURATION, 107779 useValue: options 107780 }]; 107781 return routerFeature(5 107782 /* RouterFeatureKind.RouterConfigurationFeature */ 107783 , providers); 107784} 107785/** 107786 * @license 107787 * Copyright Google LLC All Rights Reserved. 107788 * 107789 * Use of this source code is governed by an MIT-style license that can be 107790 * found in the LICENSE file at https://angular.io/license 107791 */ 107792 107793 107794const NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode; 107795/** 107796 * The directives defined in the `RouterModule`. 107797 */ 107798 107799const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent]; 107800/** 107801 * @docsNotRequired 107802 */ 107803 107804const ROUTER_FORROOT_GUARD = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken(NG_DEV_MODE ? 'router duplicate forRoot guard' : 'ROUTER_FORROOT_GUARD'); // TODO(atscott): All of these except `ActivatedRoute` are `providedIn: 'root'`. They are only kept 107805// here to avoid a breaking change whereby the provider order matters based on where the 107806// `RouterModule`/`RouterTestingModule` is imported. These can/should be removed as a "breaking" 107807// change in a major version. 107808 107809const ROUTER_PROVIDERS = [_angular_common__WEBPACK_IMPORTED_MODULE_33__.Location, { 107810 provide: UrlSerializer, 107811 useClass: DefaultUrlSerializer 107812}, { 107813 provide: Router, 107814 useFactory: setupRouter 107815}, ChildrenOutletContexts, { 107816 provide: ActivatedRoute, 107817 useFactory: rootRoute, 107818 deps: [Router] 107819}, RouterConfigLoader]; 107820 107821function routerNgProbeToken() { 107822 return new _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgProbeToken('Router', Router); 107823} 107824/** 107825 * @description 107826 * 107827 * Adds directives and providers for in-app navigation among views defined in an application. 107828 * Use the Angular `Router` service to declaratively specify application states and manage state 107829 * transitions. 107830 * 107831 * You can import this NgModule multiple times, once for each lazy-loaded bundle. 107832 * However, only one `Router` service can be active. 107833 * To ensure this, there are two ways to register routes when importing this module: 107834 * 107835 * * The `forRoot()` method creates an `NgModule` that contains all the directives, the given 107836 * routes, and the `Router` service itself. 107837 * * The `forChild()` method creates an `NgModule` that contains all the directives and the given 107838 * routes, but does not include the `Router` service. 107839 * 107840 * @see [Routing and Navigation guide](guide/router) for an 107841 * overview of how the `Router` service should be used. 107842 * 107843 * @publicApi 107844 */ 107845 107846 107847class RouterModule { 107848 constructor(guard) {} 107849 /** 107850 * Creates and configures a module with all the router providers and directives. 107851 * Optionally sets up an application listener to perform an initial navigation. 107852 * 107853 * When registering the NgModule at the root, import as follows: 107854 * 107855 * ``` 107856 * @NgModule({ 107857 * imports: [RouterModule.forRoot(ROUTES)] 107858 * }) 107859 * class MyNgModule {} 107860 * ``` 107861 * 107862 * @param routes An array of `Route` objects that define the navigation paths for the application. 107863 * @param config An `ExtraOptions` configuration object that controls how navigation is performed. 107864 * @return The new `NgModule`. 107865 * 107866 */ 107867 107868 107869 static forRoot(routes, config) { 107870 return { 107871 ngModule: RouterModule, 107872 providers: [ROUTER_PROVIDERS, NG_DEV_MODE ? config?.enableTracing ? withDebugTracing().ɵproviders : [] : [], provideRoutes(routes), { 107873 provide: ROUTER_FORROOT_GUARD, 107874 useFactory: provideForRootGuard, 107875 deps: [[Router, new _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional(), new _angular_core__WEBPACK_IMPORTED_MODULE_0__.SkipSelf()]] 107876 }, { 107877 provide: ROUTER_CONFIGURATION, 107878 useValue: config ? config : {} 107879 }, config?.useHash ? provideHashLocationStrategy() : providePathLocationStrategy(), provideRouterScroller(), config?.preloadingStrategy ? withPreloading(config.preloadingStrategy).ɵproviders : [], { 107880 provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgProbeToken, 107881 multi: true, 107882 useFactory: routerNgProbeToken 107883 }, config?.initialNavigation ? provideInitialNavigation(config) : [], provideRouterInitializer()] 107884 }; 107885 } 107886 /** 107887 * Creates a module with all the router directives and a provider registering routes, 107888 * without creating a new Router service. 107889 * When registering for submodules and lazy-loaded submodules, create the NgModule as follows: 107890 * 107891 * ``` 107892 * @NgModule({ 107893 * imports: [RouterModule.forChild(ROUTES)] 107894 * }) 107895 * class MyNgModule {} 107896 * ``` 107897 * 107898 * @param routes An array of `Route` objects that define the navigation paths for the submodule. 107899 * @return The new NgModule. 107900 * 107901 */ 107902 107903 107904 static forChild(routes) { 107905 return { 107906 ngModule: RouterModule, 107907 providers: [provideRoutes(routes)] 107908 }; 107909 } 107910 107911} 107912 107913RouterModule.ɵfac = function RouterModule_Factory(t) { 107914 return new (t || RouterModule)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](ROUTER_FORROOT_GUARD, 8)); 107915}; 107916 107917RouterModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({ 107918 type: RouterModule, 107919 imports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent], 107920 exports: [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, ɵEmptyOutletComponent] 107921}); 107922RouterModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({ 107923 imports: [ɵEmptyOutletComponent] 107924}); 107925 107926(function () { 107927 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](RouterModule, [{ 107928 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule, 107929 args: [{ 107930 imports: ROUTER_DIRECTIVES, 107931 exports: ROUTER_DIRECTIVES 107932 }] 107933 }], function () { 107934 return [{ 107935 type: undefined, 107936 decorators: [{ 107937 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 107938 }, { 107939 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 107940 args: [ROUTER_FORROOT_GUARD] 107941 }] 107942 }]; 107943 }, null); 107944})(); 107945/** 107946 * For internal use by `RouterModule` only. Note that this differs from `withInMemoryRouterScroller` 107947 * because it reads from the `ExtraOptions` which should not be used in the standalone world. 107948 */ 107949 107950 107951function provideRouterScroller() { 107952 return { 107953 provide: ROUTER_SCROLLER, 107954 useFactory: () => { 107955 const router = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(Router); 107956 const viewportScroller = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_33__.ViewportScroller); 107957 const config = (0,_angular_core__WEBPACK_IMPORTED_MODULE_0__.inject)(ROUTER_CONFIGURATION); 107958 107959 if (config.scrollOffset) { 107960 viewportScroller.setOffset(config.scrollOffset); 107961 } 107962 107963 return new RouterScroller(router, viewportScroller, config); 107964 } 107965 }; 107966} // Note: For internal use only with `RouterModule`. Standalone setup via `provideRouter` should 107967// provide hash location directly via `{provide: LocationStrategy, useClass: HashLocationStrategy}`. 107968 107969 107970function provideHashLocationStrategy() { 107971 return { 107972 provide: _angular_common__WEBPACK_IMPORTED_MODULE_33__.LocationStrategy, 107973 useClass: _angular_common__WEBPACK_IMPORTED_MODULE_33__.HashLocationStrategy 107974 }; 107975} // Note: For internal use only with `RouterModule`. Standalone setup via `provideRouter` does not 107976// need this at all because `PathLocationStrategy` is the default factory for `LocationStrategy`. 107977 107978 107979function providePathLocationStrategy() { 107980 return { 107981 provide: _angular_common__WEBPACK_IMPORTED_MODULE_33__.LocationStrategy, 107982 useClass: _angular_common__WEBPACK_IMPORTED_MODULE_33__.PathLocationStrategy 107983 }; 107984} 107985 107986function provideForRootGuard(router) { 107987 if (NG_DEV_MODE && router) { 107988 throw new _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵRuntimeError"](4007 107989 /* RuntimeErrorCode.FOR_ROOT_CALLED_TWICE */ 107990 , `The Router was provided more than once. This can happen if 'forRoot' is used outside of the root injector.` + ` Lazy loaded modules should use RouterModule.forChild() instead.`); 107991 } 107992 107993 return 'guarded'; 107994} // Note: For internal use only with `RouterModule`. Standalone router setup with `provideRouter` 107995// users call `withXInitialNavigation` directly. 107996 107997 107998function provideInitialNavigation(config) { 107999 return [config.initialNavigation === 'disabled' ? withDisabledInitialNavigation().ɵproviders : [], config.initialNavigation === 'enabledBlocking' ? withEnabledBlockingInitialNavigation().ɵproviders : []]; 108000} // TODO(atscott): This should not be in the public API 108001 108002/** 108003 * A [DI token](guide/glossary/#di-token) for the router initializer that 108004 * is called after the app is bootstrapped. 108005 * 108006 * @publicApi 108007 */ 108008 108009 108010const ROUTER_INITIALIZER = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken(NG_DEV_MODE ? 'Router Initializer' : ''); 108011 108012function provideRouterInitializer() { 108013 return [// ROUTER_INITIALIZER token should be removed. It's public API but shouldn't be. We can just 108014 // have `getBootstrapListener` directly attached to APP_BOOTSTRAP_LISTENER. 108015 { 108016 provide: ROUTER_INITIALIZER, 108017 useFactory: getBootstrapListener 108018 }, { 108019 provide: _angular_core__WEBPACK_IMPORTED_MODULE_0__.APP_BOOTSTRAP_LISTENER, 108020 multi: true, 108021 useExisting: ROUTER_INITIALIZER 108022 }]; 108023} 108024/** 108025 * @license 108026 * Copyright Google LLC All Rights Reserved. 108027 * 108028 * Use of this source code is governed by an MIT-style license that can be 108029 * found in the LICENSE file at https://angular.io/license 108030 */ 108031 108032/** 108033 * @publicApi 108034 */ 108035 108036 108037const VERSION = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.Version('14.2.10'); 108038/** 108039 * @license 108040 * Copyright Google LLC All Rights Reserved. 108041 * 108042 * Use of this source code is governed by an MIT-style license that can be 108043 * found in the LICENSE file at https://angular.io/license 108044 */ 108045 108046/** 108047 * @license 108048 * Copyright Google LLC All Rights Reserved. 108049 * 108050 * Use of this source code is governed by an MIT-style license that can be 108051 * found in the LICENSE file at https://angular.io/license 108052 */ 108053 108054/** 108055 * @license 108056 * Copyright Google LLC All Rights Reserved. 108057 * 108058 * Use of this source code is governed by an MIT-style license that can be 108059 * found in the LICENSE file at https://angular.io/license 108060 */ 108061// This file only reexports content of the `src` folder. Keep it that way. 108062 108063/** 108064 * @license 108065 * Copyright Google LLC All Rights Reserved. 108066 * 108067 * Use of this source code is governed by an MIT-style license that can be 108068 * found in the LICENSE file at https://angular.io/license 108069 */ 108070 108071/** 108072 * Generated bundle index. Do not edit. 108073 */ 108074 108075 108076 108077/***/ }), 108078 108079/***/ 2183: 108080/*!*********************************************************************!*\ 108081 !*** ./node_modules/angular-svg-icon/fesm2020/angular-svg-icon.mjs ***! 108082 \*********************************************************************/ 108083/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 108084 108085__webpack_require__.r(__webpack_exports__); 108086/* harmony export */ __webpack_require__.d(__webpack_exports__, { 108087/* harmony export */ "AngularSvgIconModule": () => (/* binding */ AngularSvgIconModule), 108088/* harmony export */ "SERVER_URL": () => (/* binding */ SERVER_URL), 108089/* harmony export */ "SVG_ICON_REGISTRY_PROVIDER": () => (/* binding */ SVG_ICON_REGISTRY_PROVIDER), 108090/* harmony export */ "SVG_ICON_REGISTRY_PROVIDER_FACTORY": () => (/* binding */ SVG_ICON_REGISTRY_PROVIDER_FACTORY), 108091/* harmony export */ "SvgHttpLoader": () => (/* binding */ SvgHttpLoader), 108092/* harmony export */ "SvgIconComponent": () => (/* binding */ SvgIconComponent), 108093/* harmony export */ "SvgIconRegistryService": () => (/* binding */ SvgIconRegistryService), 108094/* harmony export */ "SvgLoader": () => (/* binding */ SvgLoader) 108095/* harmony export */ }); 108096/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ 2560); 108097/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @angular/common */ 4666); 108098/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ 4139); 108099/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ 6587); 108100/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs/operators */ 6942); 108101/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs/operators */ 8759); 108102/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs/operators */ 7418); 108103/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs/operators */ 4661); 108104/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! rxjs/operators */ 4514); 108105/* harmony import */ var _angular_common_http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common/http */ 8987); 108106 108107 108108 108109 108110 108111 108112const _c0 = ["*"]; 108113 108114class SvgLoader {} 108115 108116class SvgHttpLoader extends SvgLoader { 108117 constructor(http) { 108118 super(); 108119 this.http = http; 108120 } 108121 108122 getSvg(url) { 108123 return this.http.get(url, { 108124 responseType: 'text' 108125 }); 108126 } 108127 108128} 108129 108130SvgHttpLoader.ɵfac = function SvgHttpLoader_Factory(t) { 108131 return new (t || SvgHttpLoader)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_common_http__WEBPACK_IMPORTED_MODULE_1__.HttpClient)); 108132}; 108133 108134SvgHttpLoader.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 108135 token: SvgHttpLoader, 108136 factory: SvgHttpLoader.ɵfac 108137}); 108138 108139(function () { 108140 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](SvgHt
108140tpLoader, [{ 108141 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable 108142 }], function () { 108143 return [{ 108144 type: _angular_common_http__WEBPACK_IMPORTED_MODULE_1__.HttpClient 108145 }]; 108146 }, null); 108147})(); 108148 108149const SERVER_URL = new _angular_core__WEBPACK_IMPORTED_MODULE_0__.InjectionToken('SERVER_URL'); 108150 108151class SvgIconRegistryService { 108152 constructor(loader, platformId, serverUrl, _document) { 108153 this.loader = loader; 108154 this.platformId = platformId; 108155 this.serverUrl = serverUrl; 108156 this._document = _document; 108157 this.iconsByUrl = new Map(); 108158 this.iconsLoadingByUrl = new Map(); 108159 this.document = this._document; 108160 } 108161 /** Add a SVG to the registry by passing a name and the SVG. */ 108162 108163 108164 addSvg(name, data) { 108165 if (!this.iconsByUrl.has(name)) { 108166 const div = this.document.createElement('DIV'); 108167 div.innerHTML = data; 108168 const svg = div.querySelector('svg'); 108169 this.iconsByUrl.set(name, svg); 108170 } 108171 } 108172 /** Load a SVG to the registry from a URL. */ 108173 108174 108175 loadSvg(url, name = url) { 108176 // not sure if there should be a possibility to use name for server usage 108177 // so overriding it for now if provided 108178 // maybe should separate functionality for url and name use-cases 108179 if (this.serverUrl && url.match(/^(http(s)?):/) === null) { 108180 url = this.serverUrl + url; 108181 name = url; 108182 } 108183 108184 if (this.iconsByUrl.has(name)) { 108185 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(this.iconsByUrl.get(name)); 108186 } else if (this.iconsLoadingByUrl.has(name)) { 108187 return this.iconsLoadingByUrl.get(name); 108188 } 108189 108190 const o = this.loader.getSvg(url).pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_3__.map)(svg => { 108191 const div = this.document.createElement('DIV'); 108192 div.innerHTML = svg; 108193 return div.querySelector('svg'); 108194 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_4__.tap)(svg => this.iconsByUrl.set(name, svg)), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.catchError)(err => { 108195 console.error(err); 108196 return (0,rxjs__WEBPACK_IMPORTED_MODULE_6__.throwError)(err); 108197 }), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_7__.finalize)(() => this.iconsLoadingByUrl.delete(name)), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_8__.share)()); 108198 this.iconsLoadingByUrl.set(name, o); 108199 return o; 108200 } 108201 /** Get loaded SVG from registry by name. (also works by url because of blended map) */ 108202 108203 108204 getSvgByName(name) { 108205 if (this.iconsByUrl.has(name)) { 108206 return (0,rxjs__WEBPACK_IMPORTED_MODULE_2__.of)(this.iconsByUrl.get(name)); 108207 } else if (this.iconsLoadingByUrl.has(name)) { 108208 return this.iconsLoadingByUrl.get(name); 108209 } 108210 108211 return (0,rxjs__WEBPACK_IMPORTED_MODULE_6__.throwError)(`No svg with name '${name}' has been loaded`); 108212 } 108213 /** Remove a SVG from the registry by URL (or name). */ 108214 108215 108216 unloadSvg(url) { 108217 if (this.iconsByUrl.has(url)) { 108218 this.iconsByUrl.delete(url); 108219 } 108220 } 108221 108222} 108223 108224SvgIconRegistryService.ɵfac = function SvgIconRegistryService_Factory(t) { 108225 return new (t || SvgIconRegistryService)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](SvgLoader), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.PLATFORM_ID), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](SERVER_URL, 8), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_9__.DOCUMENT, 8)); 108226}; 108227 108228SvgIconRegistryService.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ 108229 token: SvgIconRegistryService, 108230 factory: SvgIconRegistryService.ɵfac 108231}); 108232 108233(function () { 108234 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](SvgIconRegistryService, [{ 108235 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Injectable 108236 }], function () { 108237 return [{ 108238 type: SvgLoader 108239 }, { 108240 type: Object, 108241 decorators: [{ 108242 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 108243 args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__.PLATFORM_ID] 108244 }] 108245 }, { 108246 type: undefined, 108247 decorators: [{ 108248 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 108249 }, { 108250 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 108251 args: [SERVER_URL] 108252 }] 108253 }, {
108254 type: undefined, 108255 decorators: [{ 108256 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional 108257 }, { 108258 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Inject, 108259 args: [_angular_common__WEBPACK_IMPORTED_MODULE_9__.DOCUMENT] 108260 }] 108261 }]; 108262 }, null); 108263})(); 108264 108265function SVG_ICON_REGISTRY_PROVIDER_FACTORY(parentRegistry, loader, platformId, serverUrl, document) { 108266 return parentRegistry || new SvgIconRegistryService(loader, platformId, serverUrl, document); 108267} 108268 108269const SVG_ICON_REGISTRY_PROVIDER = { 108270 provide: SvgIconRegistryService, 108271 deps: [[new _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional(), new _angular_core__WEBPACK_IMPORTED_MODULE_0__.SkipSelf(), SvgIconRegistryService], SvgLoader, [_angular_core__WEBPACK_IMPORTED_MODULE_0__.PLATFORM_ID], [new _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional(), SERVER_URL], [new _angular_core__WEBPACK_IMPORTED_MODULE_0__.Optional(), _angular_common__WEBPACK_IMPORTED_MODULE_9__.DOCUMENT]], 108272 useFactory: SVG_ICON_REGISTRY_PROVIDER_FACTORY 108273}; 108274 108275class SvgIconHelper { 108276 constructor() { 108277 this.loaded = false; 108278 } 108279 108280} 108281 108282class SvgIconComponent { 108283 constructor(element, differs, renderer, iconReg, cdr) { 108284 this.element = element; 108285 this.differs = differs; 108286 this.renderer = renderer; 108287 this.iconReg = iconReg; 108288 this.cdr = cdr; 108289 this.stretch = false; 108290 this.applyClass = false; 108291 /** @deprecated since 9.1.0 */ 108292 108293 this.applyCss = false; 108294 this.helper = new SvgIconHelper(); 108295 this._svgStyle = null; 108296 } // Adapted from ngStyle (see: angular/packages/common/src/directives/ng_style.ts) 108297 108298 108299 set svgStyle(values) { 108300 this._svgStyle = values; 108301 108302 if (!this.helper.differ && values) { 108303 this.helper.differ = this.differs.find(values).create(); 108304 } 108305 } 108306 108307 ngOnInit() { 108308 this.init(); 108309 } 108310 108311 ngOnDestroy() { 108312 this.destroy(); 108313 } 108314 108315 ngOnChanges(changeRecord) { 108316 const elemSvg = this.element.nativeElement.firstChild; 108317 108318 if (changeRecord.src || changeRecord.name) { 108319 if (this.helper.loaded) { 108320 this.destroy(); 108321 } 108322 108323 this.init(); 108324 } 108325 108326 if (changeRecord.stretch) { 108327 this.stylize(); 108328 } 108329 108330 if (changeRecord.applyClass) { 108331 if (this.applyClass) { 108332 this.setClass(elemSvg, null, this.klass); 108333 } else { 108334 this.setClass(elemSvg, this.klass, null); 108335 } 108336 } 108337 108338 if (changeRecord.svgClass) { 108339 this.setClass(elemSvg, changeRecord.svgClass.previousValue, changeRecord.svgClass.currentValue); 108340 } 108341 108342 if (changeRecord.klass) { 108343 const elem = this.element.nativeElement; 108344 this.setClass(elem, changeRecord.klass.previousValue, changeRecord.klass.currentValue); 108345 108346 if (this.applyClass) { 108347 this.setClass(elemSvg, changeRecord.klass.previousValue, changeRecord.klass.currentValue); 108348 } else { 108349 this.setClass(elemSvg, changeRecord.klass.previousValue, null); 108350 } 108351 } 108352 108353 if (changeRecord.viewBox) { 108354 if (this.helper.loaded) { 108355 this.destroy(); 108356 } 108357 108358 this.init(); 108359 } 108360 108361 if (changeRecord.applyCss) { 108362 console.warn('applyCss deprecated since 9.1.0, will be removed in 10.0.0'); 108363 console.warn('use applyClass instead'); 108364 } 108365 108366 if (changeRecord.svgAriaLabel) { 108367 this.doAria(changeRecord.svgAriaLabel.currentValue); 108368 } 108369 } 108370 108371 ngDoCheck() { 108372 if (this.helper.svg && this.helper.differ) { 108373 const changes = this.helper.differ.diff(this._svgStyle); 108374 108375 if (changes) { 108376 this.applyChanges(changes); 108377 } 108378 } 108379 } 108380 108381 init() { 108382 if (this.name) { 108383 const svgObs = this.iconReg.getSvgByName(this.name); 108384 108385 if (svgObs) { 108386 this.helper.icnSub = svgObs.subscribe(svg => this.initSvg(svg)); 108387 } 108388 } else if (this.src) { 108389 const svgObs = this.iconReg.loadSvg(this.src); 108390 108391 if (svgObs) { 108392 this.helper.icnSub = svgObs.subscribe(svg => this.initSvg(svg)); 108393 } 108394 } else { 108395 const elem = this.element.nativeElement; 108396 elem.innerHTML = ''; 108397 this.cdr.markForCheck(); 108398 } 108399 } 108400 108401 initSvg(svg) { 108402 if (!this.helper.loaded && svg) { 108403 this.setSvg(svg); 108404 this.resetDiffer(); 108405 } 108406 } 108407 108408 destroy() { 108409 if (this.helper.icnSub) { 108410 this.helper.icnSub.unsubscribe(); 108411 } 108412 108413 this.helper = new SvgIconHelper(); 108414 } 108415 108416 resetDiffer() { 108417 if (this._svgStyle && !this.helper.differ) { 108418 this.helper.differ = this.differs.find(this._svgStyle).create(); 108419 } 108420 } 108421 108422 setSvg(svg) { 108423 if (!this.helper.loaded && svg) { 108424 this.helper.svg = svg; 108425 const icon = svg.cloneNode(true); 108426 const elem = this.element.nativeElement; 108427 elem.innerHTML = ''; 108428 this.renderer.appendChild(elem, icon); 108429 this.helper.loaded = true; 108430 this.copyNgContentAttribute(elem, icon); 108431 108432 if (this.klass && this.applyClass) { 108433 this.setClass(elem.firstChild, null, this.klass); 108434 } 108435 108436 if (this.svgClass) { 108437 this.setClass(elem.firstChild, null, this.svgClass); 108438 } 108439 108440 if (this.viewBox) { 108441 if (this.viewBox === 'auto') { 108442 // Attempt to convert height & width to a viewBox. 108443 const w = icon.getAttribute('width'); 108444 const h = icon.getAttribute('height'); 108445 108446 if (h && w) { 108447 const vb = `0 0 ${w} ${h}`; 108448 this.renderer.setAttribute(icon, 'viewBox', vb); 108449 this.renderer.removeAttribute(icon, 'width'); 108450 this.renderer.removeAttribute(icon, 'height'); 108451 } 108452 } else if (this.viewBox !== '') { 108453 this.renderer.setAttribute(icon, 'viewBox', this.viewBox); 108454 this.renderer.removeAttribute(icon, 'width'); 108455 this.renderer.removeAttribute(icon, 'height'); 108456 } 108457 } 108458 108459 this.stylize(); // If there is not a svgAriaLabel and the SVG has an arial-label, then do not override 108460 // the SVG's aria-label. 108461 108462 if (!(this.svgAriaLabel === undefined && elem.firstChild.hasAttribute('aria-label'))) { 108463 this.doAria(this.svgAriaLabel || ''); 108464 } 108465 108466 this.cdr.markForCheck(); 108467 } 108468 } 108469 108470 copyNgContentAttribute(hostElem, icon) { 108471 const attributes = hostElem.attributes; 108472 const len = attributes.length; 108473 108474 for (let i = 0; i < len; i += 1) { 108475 const attribute = attributes.item(i); 108476 108477 if (attribute && attribute.name.startsWith('_ngcontent')) { 108478 this.setNgContentAttribute(icon, attribute.name); 108479 break; 108480 } 108481 } 108482 } 108483 108484 setNgContentAttribute(parent, attributeName) { 108485 this.renderer.setAttribute(parent, attributeName, ''); 108486 const len = parent.childNodes.length; 108487 108488 for (let i = 0; i < len; i += 1) { 108489 const child = parent.childNodes[i]; 108490 108491 if (child instanceof Element) { 108492 this.setNgContentAttribute(child, attributeName); 108493 } 108494 } 108495 } 108496 108497 stylize() { 108498 if (this.helper.svg) { 108499 const svg = this.element.nativeElement.firstChild; 108500 108501 if (this.stretch === true) { 108502 this.renderer.setAttribute(svg, 'preserveAspectRatio', 'none'); 108503 } else if (this.stretch === false) { 108504 this.renderer.removeAttribute(svg, 'preserveAspectRatio'); 108505 } 108506 } 108507 } 108508 108509 applyChanges(changes) {
108510 changes.forEachRemovedItem(record => this.setStyle(record.key, null)); 108511 changes.forEachAddedItem(record => this.setStyle(record.key, record.currentValue)); 108512 changes.forEachChangedItem(record => this.setStyle(record.key, record.currentValue)); 108513 } 108514 108515 setStyle(nameAndUnit, value) { 108516 const [name, unit] = nameAndUnit.split('.'); 108517 value = value !== null && unit ? `${value}${unit}` : value; 108518 const svg = this.element.nativeElement.firstChild; 108519 108520 if (value !== null) { 108521 this.renderer.setStyle(svg, name, value); 108522 } else { 108523 this.renderer.removeStyle(svg, name); 108524 } 108525 } 108526 108527 setClass(target, previous, current) { 108528 if (target) { 108529 if (previous) { 108530 const klasses = (Array.isArray(previous) ? previous : previous.split(' ')).filter(klass => klass); 108531 108532 for (const k of klasses) { 108533 this.renderer.removeClass(target, k); 108534 } 108535 } 108536 108537 if (current) { 108538 const klasses = (Array.isArray(current) ? current : current.split(' ')).filter(klass => klass); 108539 108540 for (const k of klasses) { 108541 this.renderer.addClass(target, k); 108542 } 108543 } 108544 } 108545 } 108546 108547 doAria(label) { 108548 const svg = this.element.nativeElement.firstChild; 108549 108550 if (svg) { 108551 if (label === '') { 108552 this.renderer.setAttribute(svg, 'aria-hidden', 'true'); 108553 this.renderer.removeAttribute(svg, 'aria-label'); 108554 } else { 108555 this.renderer.removeAttribute(svg, 'aria-hidden'); 108556 this.renderer.setAttribute(svg, 'aria-label', label); 108557 } 108558 } 108559 } 108560 108561} 108562 108563SvgIconComponent.ɵfac = function SvgIconComponent_Factory(t) { 108564 return new (t || SvgIconComponent)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.KeyValueDiffers), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](SvgIconRegistryService), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef)); 108565}; 108566 108567SvgIconComponent.ɵcmp = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineComponent"]({ 108568 type: SvgIconComponent, 108569 selectors: [["svg-icon"]], 108570 inputs: { 108571 src: "src", 108572 name: "name", 108573 stretch: "stretch", 108574 applyClass: "applyClass", 108575 applyCss: "applyCss", 108576 svgClass: "svgClass", 108577 klass: ["class", "klass"], 108578 viewBox: "viewBox", 108579 svgAriaLabel: "svgAriaLabel", 108580 svgStyle: "svgStyle" 108581 }, 108582 features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]], 108583 ngContentSelectors: _c0, 108584 decls: 1, 108585 vars: 0, 108586 template: function SvgIconComponent_Template(rf, ctx) { 108587 if (rf & 1) { 108588 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵprojectionDef"](); 108589 _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵprojection"](0); 108590 } 108591 }, 108592 encapsulation: 2 108593}); 108594 108595(function () { 108596 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](SvgIconComponent, [{ 108597 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Component, 108598 args: [{ 108599 selector: 'svg-icon', 108600 template: '<ng-content></ng-content>' 108601 }] 108602 }], function () { 108603 return [{ 108604 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ElementRef 108605 }, { 108606 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.KeyValueDiffers 108607 }, { 108608 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Renderer2 108609 }, { 108610 type: SvgIconRegistryService 108611 }, { 108612 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.ChangeDetectorRef 108613 }]; 108614 }, { 108615 src: [{ 108616 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 108617 }], 108618 name: [{ 108619 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 108620 }], 108621 stretch: [{ 108622 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 108623 }], 108624 applyClass: [{ 108625 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 108626 }], 108627 applyCss: [{ 108628 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 108629 }], 108630 svgClass: [{ 108631 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 108632 }], 108633 klass: [{ 108634 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input, 108635 args: ['class'] 108636 }],
108637 viewBox: [{ 108638 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 108639 }], 108640 svgAriaLabel: [{ 108641 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 108642 }], 108643 svgStyle: [{ 108644 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.Input 108645 }] 108646 }); 108647})(); 108648 108649class AngularSvgIconModule { 108650 static forRoot(config = {}) { 108651 return { 108652 ngModule: AngularSvgIconModule, 108653 providers: [SVG_ICON_REGISTRY_PROVIDER, config.loader || { 108654 provide: SvgLoader, 108655 useClass: SvgHttpLoader 108656 }] 108657 }; 108658 } 108659 108660} 108661 108662AngularSvgIconModule.ɵfac = function AngularSvgIconModule_Factory(t) { 108663 return new (t || AngularSvgIconModule)(); 108664}; 108665 108666AngularSvgIconModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({ 108667 type: AngularSvgIconModule, 108668 declarations: [SvgIconComponent], 108669 imports: [_angular_common__WEBPACK_IMPORTED_MODULE_9__.CommonModule], 108670 exports: [SvgIconComponent] 108671}); 108672AngularSvgIconModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({ 108673 imports: [_angular_common__WEBPACK_IMPORTED_MODULE_9__.CommonModule] 108674}); 108675 108676(function () { 108677 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](AngularSvgIconModule, [{ 108678 type: _angular_core__WEBPACK_IMPORTED_MODULE_0__.NgModule, 108679 args: [{ 108680 imports: [_angular_common__WEBPACK_IMPORTED_MODULE_9__.CommonModule], 108681 declarations: [SvgIconComponent], 108682 exports: [SvgIconComponent] 108683 }] 108684 }], null, null); 108685})(); 108686/** 108687 * Generated bundle index. Do not edit. 108688 */ 108689 108690 108691 108692 108693/***/ }), 108694 108695/***/ 992: 108696/*!*****************************************************************************!*\ 108697 !*** ./node_modules/ngx-google-analytics/fesm2020/ngx-google-analytics.mjs ***! 108698 \*****************************************************************************/ 108699/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 108700 108701__webpack_require__.r(__webpack_exports__); 108702/* harmony export */ __webpack_require__.d(__webpack_exports__, { 108703/* harmony export */ "GaActionEnum": () => (/* binding */ GaActionEnum), 108704/* harmony export */ "GaEventCategoryDirective": () => (/* binding */ GaEventCategoryDirective), 108705/* harmony export */ "GaEventDirective": () => (/* binding */ GaEventDirective), 108706/* harmony export */ "GaEventFormInputDirective": () => (/* binding */ GaEventFormInputDirective), 108707/* harmony export */ "GoogleAnalyticsInitializer": () => (/* binding */ GoogleAnalyticsInitializer), 108708/* harmony export */ "GoogleAnalyticsRouterInitializer": () => (/* binding */ GoogleAnalyticsRouterInitializer), 108709/* harmony export */ "GoogleAnalyticsService": () => (/* binding */ GoogleAnalyticsService), 108710/* harmony export */ "NGX_DATA_LAYER": () => (/* binding */ NGX_DATA_LAYER), 108711/* harmony export */ "NGX_GOOGLE_ANALYTICS_INITIALIZER_PROVIDER": () => (/* binding */ NGX_GOOGLE_ANALYTICS_INITIALIZER_PROVIDER), 108712/* harmony export */ "NGX_GOOGLE_ANALYTICS_ROUTER_INITIALIZER_PROVIDER": () => (/* binding */ NGX_GOOGLE_ANALYTICS_ROUTER_INITIALIZER_PROVIDER), 108713/* harmony export */ "NGX_GOOGLE_ANALYTICS_ROUTING_SETTINGS_TOKEN": () => (/* binding */ NGX_GOOGLE_ANALYTICS_ROUTING_SETTINGS_TOKEN), 108714/* harmony export */ "NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN": () => (/* binding */ NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN), 108715/* harmony export */ "NGX_GTAG_FN": () => (/* binding */ NGX_GTAG_FN), 108716/* harmony export */ "NGX_WINDOW": () => (/* binding */ NGX_WINDOW), 108717/* harmony export */ "NgxGoogleAnalyticsModule": () => (/* binding */ NgxGoogleAnalyticsModule), 108718/* harmony export */ "NgxGoogleAnalyticsRouterModule": () => (/* binding */ NgxGoogleAnalyticsRouterModule), 108719/* harmony export */ "getDataLayerFn": () => (/* binding */ getDataLayerFn), 108720/* harmony export */ "getGtagFn": () => (/* binding */ getGtagFn) 108721/* harmony export */ }); 108722/* harmony import */ var _github_workspace_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 1670); 108723/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 2560); 108724/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ 6312); 108725/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/common */ 4666); 108726/* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/router */ 124); 108727/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs/operators */ 9151); 108728/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs/operators */ 6276); 108729 108730 108731 108732 108733 108734 108735 108736 108737class GaEventCategoryDirective { 108738 constructor() {} 108739 108740} 108741 108742GaEventCategoryDirective.ɵfac = function GaEventCategoryDirective_Factory(t) { 108743 return new (t || GaEventCategoryDirective)(); 108744}; 108745 108746GaEventCategoryDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineDirective"]({ 108747 type: GaEventCategoryDirective, 108748 selectors: [["", "gaEvent", "", "gaCategory", ""], ["", "gaCategory", ""]], 108749 inputs: { 108750 gaCategory: "gaCategory" 108751 }, 108752 exportAs: ["gaCategory"] 108753}); 108754 108755(function () { 108756 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](GaEventCategoryDirective, [{ 108757 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Directive, 108758 args: [{ 108759 selector: `[gaEvent][gaCategory], 108760 [gaCategory]`, 108761 exportAs: 'gaCategory' 108762 }] 108763 }], function () { 108764 return []; 108765 }, { 108766 gaCategory: [{ 108767 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input 108768 }] 108769 }); 108770})(); 108771/** 108772 * Provide a Injection Token to global settings. 108773 */ 108774 108775 108776const NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('ngx-google-analytics-settings', { 108777 factory: () => ({ 108778 trackingCode: '', 108779 enableTracing: false 108780 }) 108781}); 108782/** 108783 * Provide DOM Window reference. 108784 */ 108785 108786const NGX_WINDOW = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('ngx-window', { 108787 providedIn: 'root', 108788 factory: () => { 108789 const { 108790 defaultView 108791 } = (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(_angular_common__WEBPACK_IMPORTED_MODULE_2__.DOCUMENT); 108792 108793 if (!defaultView) { 108794 throw new Error('Window is not available'); 108795 } 108796 108797 return defaultView; 108798 } 108799}); 108800/** 108801 * Check if there is some global function called gtag on Window object, or create an empty function to doesn't brake codes... 108802 */ 108803 108804function getDataLayerFn(window) { 108805 return window ? window['dataLayer'] = window['dataLayer'] || [] : null; 108806} 108807/** 108808 * Provides an injection token to access Google Analytics DataLayer Collection 108809 */ 108810 108811 108812const NGX_DATA_LAYER = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('ngx-data-layer', { 108813 providedIn: 'root', 108814 factory: () => getDataLayerFn((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(NGX_WINDOW)) 108815}); 108816/** 108817 * Check if there is some global function called gtag on Window object, or create an empty function to doesn't brake codes... 108818 */ 108819 108820function getGtagFn(window, dataLayer) { 108821 return window ? window['gtag'] = window['gtag'] || function () { 108822 dataLayer.push(arguments); 108823 } : null; 108824} 108825/** 108826 * Provides an injection token to access Google Analytics Gtag Function 108827 */ 108828 108829 108830const NGX_GTAG_FN = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('ngx-gtag-fn', { 108831 providedIn: 'root', 108832 factory: () => getGtagFn((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(NGX_WINDOW), (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.inject)(NGX_DATA_LAYER)) 108833}); 108834 108835class GoogleAnalyticsService { 108836 constructor(settings, _document, _gtag) { 108837 this.settings = settings; 108838 this._document = _document; 108839 this._gtag = _gtag; 108840 } 108841 108842 get document() { 108843 return this._document; 108844 } 108845 108846 throw(err) { 108847 if ((this.settings.enableTracing || (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.isDevMode)()) && console && console.error) { 108848 console.error(err); 108849 } 108850 } 108851 /** @todo Change this to `Object.fromEntity()` in the future... */ 108852 108853 108854 toKeyValue(map) { 108855 return map.size > 0 ? Array.from(map).reduce((obj, [key, value]) => Object.defineProperty(obj, key, { 108856 value, 108857 enumerable: true 108858 }), {}) : undefined; 108859 } 108860 /** 108861 * Call native GA Tag 108862 */ 108863 108864 108865 gtag(...args) { 108866 try { 108867 this._gtag(...args.filter(x => x !== undefined)); 108868 } catch (err) { 108869 this.throw(err); 108870 } 108871 } 108872 /** 108873 * Send an event trigger to GA. It is the same as call: 108874 * ```js 108875 * gtag('event', 'video_auto_play_start', { 108876 * 'event_label': 'My promotional video', 108877 * 'event_category': 'video_auto_play' 108878 * }); 108879 * ``` 108880 * 108881 * @param action 'video_auto_play_start' 108882 * @param category 'video_auto_play' 108883 * @param label 'My promotional video' 108884 * @param value An value to measure something 108885 * @param interaction If user interaction is performed 108886 */ 108887 108888 108889 event(action, category, label, value, interaction, options) { 108890 try { 108891 const opt = new Map(); 108892 108893 if (category) { 108894 opt.set('event_category', category); 108895 } 108896 108897 if (label) { 108898 opt.set('event_label', label); 108899 } 108900 108901 if (value) { 108902 opt.set('value', value); 108903 } 108904 108905 if (interaction !== undefined) { 108906 opt.set('interaction', interaction); 108907 } 108908 108909 if (options) { 108910 Object.entries(options).map(([key, value]) => opt.set(key, value)); 108911 } 108912 108913 const params = this.toKeyValue(opt); 108914 108915 if (params) { 108916 this.gtag('event', action, params); 108917 } else { 108918 this.gtag('event', action); 108919 } 108920 } catch (error) { 108921 this.throw(error); 108922 } 108923 } 108924 /** 108925 * Send an page view event. This is the same as 108926 * 108927 * ```js 108928 * gtag('config', 'GA_TRACKING_ID', { 108929 * 'page_title' : 'Homepage', 108930 * 'page_path': '/home' 108931 * }); 108932 * ``` 108933 * 108934 * The tracking ID is injected automatically by Inject Token NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN 108935 * 108936 * @param path /home 108937 * @param title Homepage 108938 * @param location '{ page_location }' 108939 * @param options '{ ... custom dimentions }' 108940 */ 108941 108942 108943 pageView(path, title, location, options) { 108944 try { 108945 const opt = new Map([['page_path', path]]); 108946 108947 if (title) { 108948 opt.set('page_title', title); 108949 } 108950 108951 if (location || this.document) { 108952 opt.set('page_location', location || this.document.location.href); 108953 } 108954 108955 if (options) { 108956 Object.entries(options).map(([key, value]) => opt.set(key, value)); 108957 } 108958 108959 this.gtag('config', this.settings.trackingCode, this.toKeyValue(opt)); 108960 } catch (error) { 108961 this.throw(error); 108962 } 108963 } 108964 /** 108965 * Send an event to report a App Page View. It is the same as 108966 * 108967 * ```js 108968 * gtag('event', 'screen_view', { 108969 * 'app_name': 'myAppName', 108970 * 'screen_name' : 'Home' 108971 * }); 108972 * 108973 * ``` 108974 * 108975 * @param screen 'screen_name' 108976 * @param appName 'app_name'
108977 * @param appId 'app_id' 108978 * @param appVersion 'app_version' 108979 * @param installerId 'app_installer_id' 108980 */ 108981 108982 108983 appView(screen, appName, appId, appVersion, installerId) { 108984 try { 108985 const opt = new Map([['screen_name', screen], ['app_name', appName]]); 108986 108987 if (appId) { 108988 opt.set('app_id', appId); 108989 } 108990 108991 if (appVersion) { 108992 opt.set('app_version', appVersion); 108993 } 108994 108995 if (installerId) { 108996 opt.set('app_installer_id', installerId); 108997 } 108998 108999 this.gtag('event', 'screen_view', this.toKeyValue(opt)); 109000 } catch (error) { 109001 this.throw(error); 109002 } 109003 } 109004 /** 109005 * Defines persistent values on GoogleAnalytics 109006 * 109007 * @see https://developers.google.com/analytics/devguides/collection/gtagjs/setting-values 109008 * 109009 * ```js 109010 * gtag('set', { 109011 * 'currency': 'USD', 109012 * 'country': 'US' 109013 * }); 109014 * ``` 109015 */ 109016 109017 109018 set(...options) { 109019 try { 109020 this._gtag('set', ...options); 109021 } catch (err) { 109022 this.throw(err); 109023 } 109024 } 109025 /** 109026 * Send an event to GA to report an application error. It is the same as 109027 * 109028 * ```js 109029 * gtag('event', 'exception', { 109030 * 'description': 'error_description', 109031 * 'fatal': false // set to true if the error is fatal 109032 * }); 109033 * ``` 109034 * 109035 * @param description 'error_description' 109036 * @param fatal set to true if the error is fatal 109037 */ 109038 109039 109040 exception(description, fatal) { 109041 try { 109042 const opt = new Map(); 109043 109044 if (description) { 109045 opt.set('description', description); 109046 } 109047 109048 if (fatal) { 109049 opt.set('fatal', fatal); 109050 } 109051 109052 const params = this.toKeyValue(opt); 109053 109054 if (params) { 109055 this.gtag('event', 'exception', this.toKeyValue(opt)); 109056 } else { 109057 this.gtag('event', 'exception'); 109058 } 109059 } catch (error) { 109060 this.throw(error); 109061 } 109062 } 109063 109064} 109065 109066GoogleAnalyticsService.ɵfac = function GoogleAnalyticsService_Factory(t) { 109067 return new (t || GoogleAnalyticsService)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](_angular_common__WEBPACK_IMPORTED_MODULE_2__.DOCUMENT), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"](NGX_GTAG_FN)); 109068}; 109069 109070GoogleAnalyticsService.ɵprov = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"]({ 109071 token: GoogleAnalyticsService, 109072 factory: GoogleAnalyticsService.ɵfac, 109073 providedIn: 'root' 109074}); 109075 109076(function () { 109077 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](GoogleAnalyticsService, [{ 109078 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable, 109079 args: [{ 109080 providedIn: 'root' 109081 }] 109082 }], function () { 109083 return [{ 109084 type: undefined, 109085 decorators: [{ 109086 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 109087 args: [NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN] 109088 }] 109089 }, { 109090 type: undefined, 109091 decorators: [{ 109092 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 109093 args: [_angular_common__WEBPACK_IMPORTED_MODULE_2__.DOCUMENT] 109094 }] 109095 }, { 109096 type: undefined, 109097 decorators: [{ 109098 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 109099 args: [NGX_GTAG_FN] 109100 }] 109101 }]; 109102 }, null); 109103})(); 109104 109105class GaEventDirective { 109106 constructor(gaCategoryDirective, gaService, settings, el) { 109107 this.gaCategoryDirective = gaCategoryDirective; 109108 this.gaService = gaService; 109109 this.settings = settings; 109110 this.el = el; 109111 this.gaBind = 'click'; 109112 } 109113 109114 set gaBind(gaBind) { 109115 if (this.bindSubscription) { 109116 this.bindSubscription.unsubscribe(); 109117 } 109118 109119 this._gaBind = gaBind; 109120 this.bindSubscription = (0,rxjs__WEBPACK_IMPORTED_MODULE_3__.fromEvent)(this.el.nativeElement, gaBind).subscribe(() => this.trigger()); 109121 } 109122 109123 get gaBind() { 109124 return this._gaBind; 109125 } 109126 109127 ngOnDestroy() { 109128 if (this.bindSubscription) { 109129 this.bindSubscription.unsubscribe(); 109130 } 109131 } 109132 109133 trigger() { 109134 try { 109135 // Observação: não é obrigatório especificar uma categoria, uma etiqueta ou um valor. Consulte Eventos padrão do Google Analytics abaixo. 109136 // if (!this.$gaCategoryDirective) { 109137 // throw new Error('You must provide a gaCategory attribute w/ gaEvent Directive.'); 109138 // } 109139 if (!this.gaAction && !this.gaEvent) { 109140 throw new Error('You must provide a gaAction attribute to identify this event.'); 109141 } 109142
109143 this.gaService.event(this.gaAction || this.gaEvent, this.gaCategoryDirective ? this.gaCategoryDirective.gaCategory : undefined, this.gaLabel || this.label, this.gaValue, this.gaInteraction); 109144 } catch (err) { 109145 this.throw(err); 109146 } 109147 } 109148 109149 throw(err) { 109150 if (((0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.isDevMode)() || this.settings.enableTracing) && console && console.warn) { 109151 console.warn(err); 109152 } 109153 } 109154 109155} 109156 109157GaEventDirective.ɵfac = function GaEventDirective_Factory(t) { 109158 return new (t || GaEventDirective)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdirectiveInject"](GaEventCategoryDirective, 8), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdirectiveInject"](GoogleAnalyticsService), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdirectiveInject"](NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN), _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_1__.ElementRef)); 109159}; 109160 109161GaEventDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineDirective"]({ 109162 type: GaEventDirective, 109163 selectors: [["", "gaEvent", ""]], 109164 inputs: { 109165 gaAction: "gaAction", 109166 gaLabel: "gaLabel", 109167 label: "label", 109168 gaValue: "gaValue", 109169 gaInteraction: "gaInteraction", 109170 gaEvent: "gaEvent", 109171 gaBind: "gaBind" 109172 }, 109173 exportAs: ["gaEvent"] 109174}); 109175 109176(function () { 109177 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](GaEventDirective, [{ 109178 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Directive, 109179 args: [{ 109180 selector: `[gaEvent]`, 109181 exportAs: 'gaEvent' 109182 }] 109183 }], function () { 109184 return [{ 109185 type: GaEventCategoryDirective, 109186 decorators: [{ 109187 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional 109188 }] 109189 }, { 109190 type: GoogleAnalyticsService 109191 }, { 109192 type: undefined, 109193 decorators: [{ 109194 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Inject, 109195 args: [NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN] 109196 }] 109197 }, { 109198 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.ElementRef 109199 }]; 109200 }, { 109201 gaAction: [{ 109202 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input 109203 }], 109204 gaLabel: [{ 109205 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input 109206 }], 109207 label: [{ 109208 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input 109209 }], 109210 gaValue: [{ 109211 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input 109212 }], 109213 gaInteraction: [{ 109214 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input 109215 }], 109216 gaEvent: [{ 109217 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input 109218 }], 109219 gaBind: [{ 109220 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input 109221 }] 109222 }); 109223})(); 109224 109225class GaEventFormInputDirective { 109226 constructor(gaEvent) { 109227 this.gaEvent = gaEvent; 109228 this.gaBind = 'focus'; 109229 } 109230 109231 set gaBind(bind) { 109232 if (this.gaEvent) { 109233 this.gaEvent.gaBind = bind; 109234 } 109235 } 109236 109237} 109238 109239GaEventFormInputDirective.ɵfac = function GaEventFormInputDirective_Factory(t) { 109240 return new (t || GaEventFormInputDirective)(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdirectiveInject"](GaEventDirective, 9)); 109241}; 109242 109243GaEventFormInputDirective.ɵdir = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineDirective"]({ 109244 type: GaEventFormInputDirective, 109245 selectors: [["input", "gaEvent", ""], ["select", "gaEvent", ""], ["textarea", "gaEvent", ""]], 109246 inputs: { 109247 gaBind: "gaBind" 109248 } 109249}); 109250 109251(function () { 109252 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](GaEventFormInputDirective, [{ 109253 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Directive, 109254 args: [{ 109255 selector: `input[gaEvent], 109256 select[gaEvent], 109257 textarea[gaEvent]` 109258 }] 109259 }], function () { 109260 return [{ 109261 type: GaEventDirective, 109262 decorators: [{ 109263 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Host 109264 }, { 109265 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Optional 109266 }] 109267 }]; 109268 }, { 109269 gaBind: [{ 109270 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.Input 109271 }] 109272 }); 109273})(); 109274 109275var GaActionEnum; 109276 109277(function (GaActionEnum) { 109278 GaActionEnum["ADD_PAYMENT_INFO"] = "add_payment_info"; 109279 GaActionEnum["ADD_TO_CART"] = "add_to_cart"; 109280 GaActionEnum["ADD_TO_WISHLIST"] = "add_to_wishlist"; 109281 GaActionEnum["BEGIN_CHECKOUT"] = "begin_checkout"; 109282 GaActionEnum["CHECKOUT_PROGRESS"] = "checkout_progress"; 109283 GaActionEnum["GENERATE_LEAD"] = "generate_lead"; 109284 GaActionEnum["LOGIN"] = "login"; 109285 GaActionEnum["PURCHASE"] = "purchase"; 109286 GaActionEnum["REFUND"] = "refund"; 109287 GaActionEnum["REMOVE_FROM_CART"] = "remove_from_cart"; 109288 GaActionEnum["SEARCH"] = "search"; 109289 GaActionEnum["SELECT_CONTENT"] = "select_content"; 109290 GaActionEnum["SET_CHECKOUT_OPTION"] = "set_checkout_option"; 109291 GaActionEnum["SHARE"] = "share"; 109292 GaActionEnum["SIGN_UP"] = "sign_up";
109293 GaActionEnum["VIEW_ITEM"] = "view_item"; 109294 GaActionEnum["VIEW_ITEM_LIST"] = "view_item_list"; 109295 GaActionEnum["VIEW_PROMOTION"] = "view_promotion"; 109296 GaActionEnum["VIEW_SEARCH_RESULT"] = "view_search_results"; 109297 GaActionEnum["VIEW_SEARCH_RESULTS"] = "view_search_results"; 109298})(GaActionEnum || (GaActionEnum = {})); 109299/** 109300 * Provide a DI Configuration to attach GA Initialization at Angular Startup Cycle. 109301 */ 109302 109303 109304const NGX_GOOGLE_ANALYTICS_INITIALIZER_PROVIDER = { 109305 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_INITIALIZER, 109306 multi: true, 109307 useFactory: GoogleAnalyticsInitializer, 109308 deps: [NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN, NGX_GTAG_FN, _angular_common__WEBPACK_IMPORTED_MODULE_2__.DOCUMENT] 109309}; 109310/** 109311 * Create a script element on DOM and link it to Google Analytics tracking code URI. 109312 * After that, execute exactly same init process as tracking snippet code. 109313 */ 109314 109315function GoogleAnalyticsInitializer(settings, gtag, document) { 109316 return /*#__PURE__*/(0,_github_workspace_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { 109317 if (!settings.trackingCode) { 109318 if (!(0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.isDevMode)()) { 109319 console.error('Empty tracking code for Google Analytics. Make sure to provide one when initializing NgxGoogleAnalyticsModule.'); 109320 } 109321 109322 return; 109323 } 109324 109325 if (!gtag) { 109326 if (!(0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.isDevMode)()) { 109327 console.error('Was not possible create or read gtag() fn. Make sure this module is running on a Browser w/ access to Window interface.'); 109328 } 109329 109330 return; 109331 } 109332 109333 if (!document) { 109334 if (!(0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.isDevMode)()) { 109335 console.error('Was not possible to access Document interface. Make sure this module is running on a Browser w/ access do Document interface.'); 109336 } 109337 } // Set default ga.js uri 109338 109339 109340 settings.uri = settings.uri || `https://www.googletagmanager.com/gtag/js?id=${settings.trackingCode}`; // these commands should run first! 109341 109342 settings.initCommands = settings?.initCommands ?? []; // assert config command 109343 109344 if (!settings.initCommands.find(x => x.command === 'config')) { 109345 settings.initCommands.unshift({ 109346 command: 'config', 109347 values: [settings.trackingCode] 109348 }); 109349 } // assert js command 109350 109351 109352 if (!settings.initCommands.find(x => x.command === 'js')) { 109353 settings.initCommands.unshift({ 109354 command: 'js', 109355 values: [new Date()] 109356 }); 109357 } 109358 109359 for (const command of settings.initCommands) { 109360 gtag(command.command, ...command.values); 109361 } 109362 109363 const s = document.createElement('script'); 109364 s.async = true; 109365 s.src = settings.uri; 109366 109367 if (settings.nonce) { 109368 s.setAttribute('nonce', settings.nonce); 109369 } 109370 109371 const head = document.getElementsByTagName('head')[0]; 109372 head.appendChild(s); 109373 }); 109374} 109375/** 109376 * Provide a Injection Token to global settings. 109377 */ 109378 109379 109380const NGX_GOOGLE_ANALYTICS_ROUTING_SETTINGS_TOKEN = new _angular_core__WEBPACK_IMPORTED_MODULE_1__.InjectionToken('ngx-google-analytics-routing-settings', { 109381 factory: () => ({}) 109382}); 109383/** 109384 * Provide a DI Configuration to attach GA Trigger to Router Events at Angular Startup Cycle. 109385 */ 109386 109387const NGX_GOOGLE_ANALYTICS_ROUTER_INITIALIZER_PROVIDER = { 109388 provide: _angular_core__WEBPACK_IMPORTED_MODULE_1__.APP_BOOTSTRAP_LISTENER, 109389 multi: true, 109390 useFactory: GoogleAnalyticsRouterInitializer, 109391 deps: [NGX_GOOGLE_ANALYTICS_ROUTING_SETTINGS_TOKEN, GoogleAnalyticsService] 109392}; 109393/** 109394 * Attach a listener to `NavigationEnd` Router event. So, every time Router finish the page resolution it should call `NavigationEnd` event. 109395 * We assume that NavigationEnd is the final page resolution and call GA `page_view` command. 109396 * 109397 * To avoid double binds, we also destroy the subscription when de Bootstrap Component is destroied. But, we don't know for sure 109398 * that this strategy does not cause double bind on multiple bootstrap components. 109399 * 109400 * We are using de component's injector reference to resolve Router, sou I hope there is no problem w/ double bing. 109401 * 109402 * If you have this problem, I encourage not Use NgxGoogleAnalyticsRouterModule and atach the listener on AppComponent initialization. 109403 */ 109404 109405function GoogleAnalyticsRouterInitializer(settings, gaService) { 109406 return /*#__PURE__*/function () { 109407 var _ref2 = (0,_github_workspace_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (c) { 109408 const router = c.injector.get(_angular_router__WEBPACK_IMPORTED_MODULE_4__.Router); 109409 const { 109410 include = [], 109411 exclude = [] 109412 } = settings ?? {}; 109413 const includeRules = normalizePathRules(include); 109414 const excludeRules = normalizePathRules(exclude); 109415 const subs = router.events.pipe((0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.filter)(event => event instanceof _angular_router__WEBPACK_IMPORTED_MODULE_4__.NavigationEnd), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_6__.skip)(1), // Prevend double views on the first tigger (because GA Already send one ping on setup) 109416 (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.filter)(event => includeRules.length > 0 ? includeRules.some(rule => rule.test(event.urlAfterRedirects)) : true), (0,rxjs_operators__WEBPACK_IMPORTED_MODULE_5__.filter)(event => excludeRules.length > 0 ? !excludeRules.some(rule => rule.test(event.urlAfterRedirects)) : true)).subscribe(event => gaService.pageView(event.urlAfterRedirects, undefined)); // Cleanup 109417 109418 c.onDestroy(() => subs.unsubscribe()); 109419 }); 109420 109421 return function (_x) { 109422 return _ref2.apply(this, arguments); 109423 }; 109424 }(); 109425} 109426/** Converts all path rules from string to Regex instances */ 109427 109428 109429function normalizePathRules(rules) { 109430 return rules.map(rule => rule instanceof RegExp ? rule : new RegExp(`^${rule.replace('*', '.*')}$`, 'i')); 109431} 109432/** 109433 * Install Google Analytics Tracking code on your environment and configure tracking ID. 109434 * 109435 * This module should be a dependency on the highest level module of the application, i.e. AppModule in most use cases. 109436 */ 109437 109438 109439class NgxGoogleAnalyticsModule { 109440 /** 109441 * You should provide a valid Google TrackingCode. This code will be provided to the entire application by 109442 * `NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN` token. You can inject this code in you components if you like by 109443 * use the following injection code `@Inject(NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN) gaConfig: IGoogleAnalyticsSettings` 109444 * 109445 * @param trackingCode The Google Tracking Code
109446 * @param initCommands When placed, it will run any GA Commands in sequence after setup GA environment. 109447 * @param uri When placed, it will change the default js URI to the provided one. 109448 * @param enableTracing When true, trace GA tracking errors on production mode. 109449 * @param nonce When placed, nonce will be added to script tag. 109450 */ 109451 static forRoot(trackingCode, initCommands = [], uri, enableTracing, nonce) { 109452 return { 109453 ngModule: NgxGoogleAnalyticsModule, 109454 providers: [{ 109455 provide: NGX_GOOGLE_ANALYTICS_SETTINGS_TOKEN, 109456 useValue: { 109457 trackingCode, 109458 initCommands, 109459 uri, 109460 enableTracing, 109461 nonce 109462 } 109463 }, NGX_GOOGLE_ANALYTICS_INITIALIZER_PROVIDER] 109464 }; 109465 } 109466 109467} 109468 109469NgxGoogleAnalyticsModule.ɵfac = function NgxGoogleAnalyticsModule_Factory(t) { 109470 return new (t || NgxGoogleAnalyticsModule)(); 109471}; 109472 109473NgxGoogleAnalyticsModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineNgModule"]({ 109474 type: NgxGoogleAnalyticsModule, 109475 declarations: [GaEventDirective, GaEventCategoryDirective, GaEventFormInputDirective], 109476 exports: [GaEventDirective, GaEventCategoryDirective, GaEventFormInputDirective] 109477}); 109478NgxGoogleAnalyticsModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjector"]({}); 109479 109480(function () { 109481 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](NgxGoogleAnalyticsModule, [{ 109482 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgModule, 109483 args: [{ 109484 imports: [], 109485 declarations: [GaEventDirective, GaEventCategoryDirective, GaEventFormInputDirective], 109486 exports: [GaEventDirective, GaEventCategoryDirective, GaEventFormInputDirective] 109487 }] 109488 }], null, null); 109489})(); 109490/** 109491 * Attach a listener to `NavigationEnd` Router event. So, every time Router finish the page resolution it should call `NavigationEnd` event. 109492 * We assume that NavigationEnd is the final page resolution and call GA `page_view` command. 109493 * 109494 * To avoid double binds, we also destroy the subscription when de Bootstrap Component is destroied. But, we don't know for sure 109495 * that this strategy does not cause double bind on multiple bootstrap components. 109496 * 109497 * We are using de component's injector reference to resolve Router, sou I hope there is no problem w/ double bing. 109498 * 109499 * If you have this problem, I encourage not Use NgxGoogleAnalyticsRouterModule and atach the listener on AppComponent initialization. 109500 * 109501 * This Module is just a sugar for: 109502 * 109503```typescript 109504constructor(private router: Router) {} 109505... 109506ngOnInit() { 109507 ... 109508 this.router 109509 .events 109510 .pipe(takeUntil(this.onDestroy$)) 109511 .subscribe(event => { 109512 if (event instanceof NavigationEnd) { 109513 gaService.pageView(event.urlAfterRedirects, undefined); 109514 } 109515 }); 109516``` 109517 */ 109518 109519 109520class NgxGoogleAnalyticsRouterModule { 109521 static forRoot(settings) { 109522 return { 109523 ngModule: NgxGoogleAnalyticsRouterModule, 109524 providers: [{ 109525 provide: NGX_GOOGLE_ANALYTICS_ROUTING_SETTINGS_TOKEN, 109526 useValue: settings ?? {} 109527 }] 109528 }; 109529 } 109530 109531} 109532 109533NgxGoogleAnalyticsRouterModule.ɵfac = function NgxGoogleAnalyticsRouterModule_Factory(t) { 109534 return new (t || NgxGoogleAnalyticsRouterModule)(); 109535}; 109536 109537NgxGoogleAnalyticsRouterModule.ɵmod = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineNgModule"]({ 109538 type: NgxGoogleAnalyticsRouterModule, 109539 imports: [_angular_common__WEBPACK_IMPORTED_MODULE_2__.CommonModule, NgxGoogleAnalyticsModule] 109540}); 109541NgxGoogleAnalyticsRouterModule.ɵinj = /* @__PURE__ */_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjector"]({ 109542 providers: [NGX_GOOGLE_ANALYTICS_ROUTER_INITIALIZER_PROVIDER], 109543 imports: [_angular_common__WEBPACK_IMPORTED_MODULE_2__.CommonModule, NgxGoogleAnalyticsModule] 109544}); 109545 109546(function () { 109547 (typeof ngDevMode === "undefined" || ngDevMode) && _angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵsetClassMetadata"](NgxGoogleAnalyticsRouterModule, [{ 109548 type: _angular_core__WEBPACK_IMPORTED_MODULE_1__.NgModule, 109549 args: [{ 109550 imports: [_angular_common__WEBPACK_IMPORTED_MODULE_2__.CommonModule, NgxGoogleAnalyticsModule], 109551 providers: [NGX_GOOGLE_ANALYTICS_ROUTER_INITIALIZER_PROVIDER], 109552 declarations: [] 109553 }] 109554 }], null, null); 109555})(); 109556/* 109557 * Public API Surface of ngx-google-analytics 109558 */ 109559 109560/** 109561 * Generated bundle index. Do not edit. 109562 */ 109563 109564 109565 109566 109567/***/ }), 109568 109569/***/ 1670: 109570/*!*********************************************************************!*\ 109571 !*** ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js ***! 109572 \*********************************************************************/ 109573/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 109574 109575__webpack_require__.r(__webpack_exports__); 109576/* harmony export */ __webpack_require__.d(__webpack_exports__, { 109577/* harmony export */ "default": () => (/* binding */ _asyncToGenerator) 109578/* harmony export */ }); 109579function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { 109580 try { 109581 var info = gen[key](arg); 109582 var value = info.value; 109583 } catch (error) { 109584 reject(error); 109585 return; 109586 } 109587 109588 if (info.done) { 109589 resolve(value); 109590 } else { 109591 Promise.resolve(value).then(_next, _throw); 109592 } 109593} 109594 109595function _asyncToGenerator(fn) { 109596 return function () { 109597 var self = this, 109598 args = arguments; 109599 return new Promise(function (resolve, reject) { 109600 var gen = fn.apply(self, args); 109601 109602 function _next(value) { 109603 asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); 109604 } 109605 109606 function _throw(err) { 109607 asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); 109608 } 109609 109610 _next(undefined); 109611 }); 109612 }; 109613} 109614 109615/***/ }) 109616 109617}]); 109618//# sourceMappingURL=vendor.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.