( ast: I18nNode[], tView: TView, tIcu: TIcu, lView: LView, sharedUpdateOpCodes: I18nUpdateOpCodes, create: IcuCreateOpCodes, remove: I18nRemoveOpCodes, update: I18nUpdateOpCodes, parentNode: Element, parentIdx: number, nestedIcus: IcuExpression[], depth: number, )
| 787 | } |
| 788 | |
| 789 | function walkIcuTree( |
| 790 | ast: I18nNode[], |
| 791 | tView: TView, |
| 792 | tIcu: TIcu, |
| 793 | lView: LView, |
| 794 | sharedUpdateOpCodes: I18nUpdateOpCodes, |
| 795 | create: IcuCreateOpCodes, |
| 796 | remove: I18nRemoveOpCodes, |
| 797 | update: I18nUpdateOpCodes, |
| 798 | parentNode: Element, |
| 799 | parentIdx: number, |
| 800 | nestedIcus: IcuExpression[], |
| 801 | depth: number, |
| 802 | ): number { |
| 803 | let bindingMask = 0; |
| 804 | let currentNode = parentNode.firstChild; |
| 805 | while (currentNode) { |
| 806 | const newIndex = allocExpando(tView, lView, 1, null); |
| 807 | switch (currentNode.nodeType) { |
| 808 | case Node.ELEMENT_NODE: |
| 809 | const element = currentNode as Element; |
| 810 | const tagName = element.tagName.toLowerCase(); |
| 811 | if (VALID_ELEMENTS.hasOwnProperty(tagName)) { |
| 812 | addCreateNodeAndAppend(create, ELEMENT_MARKER, tagName, parentIdx, newIndex); |
| 813 | tView.data[newIndex] = tagName; |
| 814 | const elAttrs = element.attributes; |
| 815 | for (let i = 0; i < elAttrs.length; i++) { |
| 816 | const attr = elAttrs.item(i)!; |
| 817 | const lowerAttrName = attr.name.toLowerCase(); |
| 818 | const hasBinding = !!attr.value.match(BINDING_REGEXP); |
| 819 | const namespaceUri = element.namespaceURI; |
| 820 | const namespace = namespaceUri && NAMESPACE_URIS[namespaceUri]; |
| 821 | const tagNameWithNamespace = namespace ? `:${namespace}:${tagName}` : tagName; |
| 822 | |
| 823 | if (hasBinding) { |
| 824 | if (VALID_ATTRS.hasOwnProperty(lowerAttrName)) { |
| 825 | generateBindingUpdateOpCodes( |
| 826 | update, |
| 827 | attr.value, |
| 828 | newIndex, |
| 829 | attr.name, |
| 830 | 0, |
| 831 | i18nResolveSanitizer(lowerAttrName, tagNameWithNamespace), |
| 832 | ); |
| 833 | } else { |
| 834 | ngDevMode && |
| 835 | console.warn( |
| 836 | `WARNING: ignoring unsafe attribute value ` + |
| 837 | `${lowerAttrName} on element ${tagName} ` + |
| 838 | `(see ${XSS_SECURITY_URL})`, |
| 839 | ); |
| 840 | } |
| 841 | } else if (VALID_ATTRS[lowerAttrName]) { |
| 842 | let val = attr.value; |
| 843 | const sanitizer = i18nResolveSanitizer(lowerAttrName, tagNameWithNamespace); |
| 844 | if (sanitizer) { |
| 845 | if (typeof ngDevMode !== 'undefined' && ngDevMode) { |
| 846 | console.warn( |
no test coverage detected