refactor(ivy): remove ɵɵelementAttribute instruction (#30640)
PR Close #30640
This commit is contained in:
		
							parent
							
								
									30efb6b8ea
								
							
						
					
					
						commit
						3859bcc70c
					
				| @ -37,8 +37,6 @@ export class Identifiers { | |||||||
|   static componentHostSyntheticListener: |   static componentHostSyntheticListener: | ||||||
|       o.ExternalReference = {name: 'ɵɵcomponentHostSyntheticListener', moduleName: CORE}; |       o.ExternalReference = {name: 'ɵɵcomponentHostSyntheticListener', moduleName: CORE}; | ||||||
| 
 | 
 | ||||||
|   static elementAttribute: o.ExternalReference = {name: 'ɵɵelementAttribute', moduleName: CORE}; |  | ||||||
| 
 |  | ||||||
|   static attribute: o.ExternalReference = {name: 'ɵɵattribute', moduleName: CORE}; |   static attribute: o.ExternalReference = {name: 'ɵɵattribute', moduleName: CORE}; | ||||||
| 
 | 
 | ||||||
|   static attributeInterpolate1: |   static attributeInterpolate1: | ||||||
|  | |||||||
| @ -126,7 +126,6 @@ export { | |||||||
|   ɵɵenableBindings, |   ɵɵenableBindings, | ||||||
|   ɵɵdisableBindings, |   ɵɵdisableBindings, | ||||||
|   ɵɵallocHostVars, |   ɵɵallocHostVars, | ||||||
|   ɵɵelementAttribute, |  | ||||||
|   ɵɵelementContainerStart, |   ɵɵelementContainerStart, | ||||||
|   ɵɵelementContainerEnd, |   ɵɵelementContainerEnd, | ||||||
|   ɵɵstyling, |   ɵɵstyling, | ||||||
|  | |||||||
| @ -7,16 +7,18 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| import '../util/ng_i18n_closure_mode'; | import '../util/ng_i18n_closure_mode'; | ||||||
|  | 
 | ||||||
| import {getPluralCase} from '../i18n/localization'; | import {getPluralCase} from '../i18n/localization'; | ||||||
| import {SRCSET_ATTRS, URI_ATTRS, VALID_ATTRS, VALID_ELEMENTS, getTemplateContent} from '../sanitization/html_sanitizer'; | import {SRCSET_ATTRS, URI_ATTRS, VALID_ATTRS, VALID_ELEMENTS, getTemplateContent} from '../sanitization/html_sanitizer'; | ||||||
| import {InertBodyHelper} from '../sanitization/inert_body'; | import {InertBodyHelper} from '../sanitization/inert_body'; | ||||||
| import {_sanitizeUrl, sanitizeSrcset} from '../sanitization/url_sanitizer'; | import {_sanitizeUrl, sanitizeSrcset} from '../sanitization/url_sanitizer'; | ||||||
| import {addAllToArray} from '../util/array_utils'; | import {addAllToArray} from '../util/array_utils'; | ||||||
| import {assertDataInRange, assertDefined, assertEqual, assertGreaterThan} from '../util/assert'; | import {assertDataInRange, assertDefined, assertEqual, assertGreaterThan} from '../util/assert'; | ||||||
|  | 
 | ||||||
| import {attachPatchData} from './context_discovery'; | import {attachPatchData} from './context_discovery'; | ||||||
| import {elementAttributeInternal, setDelayProjection, ɵɵload, ɵɵtextBinding} from './instructions/all'; | import {setDelayProjection, ɵɵload, ɵɵtextBinding} from './instructions/all'; | ||||||
| import {attachI18nOpCodesDebug} from './instructions/lview_debug'; | import {attachI18nOpCodesDebug} from './instructions/lview_debug'; | ||||||
| import {allocExpando, elementPropertyInternal, getOrCreateTNode, setInputsForProperty} from './instructions/shared'; | import {allocExpando, elementAttributeInternal, elementPropertyInternal, getOrCreateTNode, setInputsForProperty} from './instructions/shared'; | ||||||
| import {LContainer, NATIVE} from './interfaces/container'; | import {LContainer, NATIVE} from './interfaces/container'; | ||||||
| import {COMMENT_MARKER, ELEMENT_MARKER, I18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, IcuType, TI18n, TIcu} from './interfaces/i18n'; | import {COMMENT_MARKER, ELEMENT_MARKER, I18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, IcuType, TI18n, TIcu} from './interfaces/i18n'; | ||||||
| import {TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeType, TProjectionNode} from './interfaces/node'; | import {TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeType, TProjectionNode} from './interfaces/node'; | ||||||
| @ -755,10 +757,9 @@ function readCreateOpCodes( | |||||||
|           const elementNodeIndex = opCode >>> I18nMutateOpCode.SHIFT_REF; |           const elementNodeIndex = opCode >>> I18nMutateOpCode.SHIFT_REF; | ||||||
|           const attrName = createOpCodes[++i] as string; |           const attrName = createOpCodes[++i] as string; | ||||||
|           const attrValue = createOpCodes[++i] as string; |           const attrValue = createOpCodes[++i] as string; | ||||||
|           const renderer = viewData[RENDERER]; |  | ||||||
|           // This code is used for ICU expressions only, since we don't support
 |           // This code is used for ICU expressions only, since we don't support
 | ||||||
|           // directives/components in ICUs, we don't need to worry about inputs here
 |           // directives/components in ICUs, we don't need to worry about inputs here
 | ||||||
|           elementAttributeInternal(elementNodeIndex, attrName, attrValue, viewData, renderer); |           elementAttributeInternal(elementNodeIndex, attrName, attrValue, viewData); | ||||||
|           break; |           break; | ||||||
|         default: |         default: | ||||||
|           throw new Error(`Unable to determine the type of mutate operation for "${opCode}"`); |           throw new Error(`Unable to determine the type of mutate operation for "${opCode}"`); | ||||||
| @ -988,8 +989,7 @@ function i18nAttributesFirstPass(tView: TView, index: number, values: string[]) | |||||||
|               generateBindingUpdateOpCodes(value, previousElementIndex, attrName), updateOpCodes); |               generateBindingUpdateOpCodes(value, previousElementIndex, attrName), updateOpCodes); | ||||||
|         } else { |         } else { | ||||||
|           const lView = getLView(); |           const lView = getLView(); | ||||||
|           const renderer = lView[RENDERER]; |           elementAttributeInternal(previousElementIndex, attrName, value, lView); | ||||||
|           elementAttributeInternal(previousElementIndex, attrName, value, lView, renderer); |  | ||||||
|           // Check if that attribute is a directive input
 |           // Check if that attribute is a directive input
 | ||||||
|           const tNode = getTNode(previousElementIndex, lView); |           const tNode = getTNode(previousElementIndex, lView); | ||||||
|           const dataValue = tNode.inputs && tNode.inputs[attrName]; |           const dataValue = tNode.inputs && tNode.inputs[attrName]; | ||||||
|  | |||||||
| @ -47,7 +47,6 @@ export { | |||||||
|   ɵɵdirectiveInject, |   ɵɵdirectiveInject, | ||||||
| 
 | 
 | ||||||
|   ɵɵelement, |   ɵɵelement, | ||||||
|   ɵɵelementAttribute, |  | ||||||
|   ɵɵelementContainerEnd, |   ɵɵelementContainerEnd, | ||||||
| 
 | 
 | ||||||
|   ɵɵelementContainerStart, |   ɵɵelementContainerStart, | ||||||
|  | |||||||
| @ -6,10 +6,13 @@ | |||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {SanitizerFn} from '../interfaces/sanitization'; | import {SanitizerFn} from '../interfaces/sanitization'; | ||||||
| import {getSelectedIndex} from '../state'; | import {getLView, getSelectedIndex} from '../state'; | ||||||
|  | import {NO_CHANGE} from '../tokens'; | ||||||
| 
 | 
 | ||||||
| import {ɵɵelementAttribute} from './element'; |  | ||||||
| import {ɵɵbind} from './property'; | import {ɵɵbind} from './property'; | ||||||
|  | import {elementAttributeInternal} from './shared'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Updates the value of or removes a bound attribute on an Element. |  * Updates the value of or removes a bound attribute on an Element. | ||||||
| @ -27,6 +30,10 @@ import {ɵɵbind} from './property'; | |||||||
| export function ɵɵattribute( | export function ɵɵattribute( | ||||||
|     name: string, value: any, sanitizer?: SanitizerFn | null, namespace?: string) { |     name: string, value: any, sanitizer?: SanitizerFn | null, namespace?: string) { | ||||||
|   const index = getSelectedIndex(); |   const index = getSelectedIndex(); | ||||||
|  |   const lView = getLView(); | ||||||
|   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 |   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 | ||||||
|   return ɵɵelementAttribute(index, name, ɵɵbind(value), sanitizer, namespace); |   const bound = ɵɵbind(value); | ||||||
|  |   if (bound !== NO_CHANGE) { | ||||||
|  |     return elementAttributeInternal(index, name, bound, lView, sanitizer, namespace); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -6,10 +6,11 @@ | |||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {SanitizerFn} from '../interfaces/sanitization'; | import {SanitizerFn} from '../interfaces/sanitization'; | ||||||
| import {getSelectedIndex} from '../state'; | import {getLView, getSelectedIndex} from '../state'; | ||||||
| import {ɵɵelementAttribute} from './element'; | import {NO_CHANGE} from '../tokens'; | ||||||
|  | 
 | ||||||
| import {ɵɵinterpolation1, ɵɵinterpolation2, ɵɵinterpolation3, ɵɵinterpolation4, ɵɵinterpolation5, ɵɵinterpolation6, ɵɵinterpolation7, ɵɵinterpolation8, ɵɵinterpolationV} from './interpolation'; | import {ɵɵinterpolation1, ɵɵinterpolation2, ɵɵinterpolation3, ɵɵinterpolation4, ɵɵinterpolation5, ɵɵinterpolation6, ɵɵinterpolation7, ɵɵinterpolation8, ɵɵinterpolationV} from './interpolation'; | ||||||
| import {TsickleIssue1009} from './shared'; | import {TsickleIssue1009, elementAttributeInternal} from './shared'; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -41,12 +42,13 @@ export function ɵɵattributeInterpolate1( | |||||||
|     attrName: string, prefix: string, v0: any, suffix: string, sanitizer?: SanitizerFn, |     attrName: string, prefix: string, v0: any, suffix: string, sanitizer?: SanitizerFn, | ||||||
|     namespace?: string): TsickleIssue1009 { |     namespace?: string): TsickleIssue1009 { | ||||||
|   const index = getSelectedIndex(); |   const index = getSelectedIndex(); | ||||||
|  |   const lView = getLView(); | ||||||
| 
 | 
 | ||||||
|   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 |   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 | ||||||
|   const interpolatedValue = ɵɵinterpolation1(prefix, v0, suffix); |   const interpolatedValue = ɵɵinterpolation1(prefix, v0, suffix); | ||||||
| 
 |   if (interpolatedValue !== NO_CHANGE) { | ||||||
|   ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace); |     elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace); | ||||||
| 
 |   } | ||||||
|   return ɵɵattributeInterpolate1; |   return ɵɵattributeInterpolate1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -80,10 +82,13 @@ export function ɵɵattributeInterpolate2( | |||||||
|     attrName: string, prefix: string, v0: any, i0: string, v1: any, suffix: string, |     attrName: string, prefix: string, v0: any, i0: string, v1: any, suffix: string, | ||||||
|     sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 { |     sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 { | ||||||
|   const index = getSelectedIndex(); |   const index = getSelectedIndex(); | ||||||
|  |   const lView = getLView(); | ||||||
| 
 | 
 | ||||||
|   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 |   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 | ||||||
|   const interpolatedValue = ɵɵinterpolation2(prefix, v0, i0, v1, suffix); |   const interpolatedValue = ɵɵinterpolation2(prefix, v0, i0, v1, suffix); | ||||||
|   ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace); |   if (interpolatedValue !== NO_CHANGE) { | ||||||
|  |     elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace); | ||||||
|  |   } | ||||||
|   return ɵɵattributeInterpolate2; |   return ɵɵattributeInterpolate2; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -120,10 +125,13 @@ export function ɵɵattributeInterpolate3( | |||||||
|     attrName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, |     attrName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, | ||||||
|     suffix: string, sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 { |     suffix: string, sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 { | ||||||
|   const index = getSelectedIndex(); |   const index = getSelectedIndex(); | ||||||
|  |   const lView = getLView(); | ||||||
| 
 | 
 | ||||||
|   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 |   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 | ||||||
|   const interpolatedValue = ɵɵinterpolation3(prefix, v0, i0, v1, i1, v2, suffix); |   const interpolatedValue = ɵɵinterpolation3(prefix, v0, i0, v1, i1, v2, suffix); | ||||||
|   ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace); |   if (interpolatedValue !== NO_CHANGE) { | ||||||
|  |     elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace); | ||||||
|  |   } | ||||||
|   return ɵɵattributeInterpolate3; |   return ɵɵattributeInterpolate3; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -162,10 +170,13 @@ export function ɵɵattributeInterpolate4( | |||||||
|     attrName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, |     attrName: string, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, | ||||||
|     v3: any, suffix: string, sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 { |     v3: any, suffix: string, sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 { | ||||||
|   const index = getSelectedIndex(); |   const index = getSelectedIndex(); | ||||||
|  |   const lView = getLView(); | ||||||
| 
 | 
 | ||||||
|   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 |   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 | ||||||
|   const interpolatedValue = ɵɵinterpolation4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix); |   const interpolatedValue = ɵɵinterpolation4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix); | ||||||
|   ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace); |   if (interpolatedValue !== NO_CHANGE) { | ||||||
|  |     elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace); | ||||||
|  |   } | ||||||
|   return ɵɵattributeInterpolate4; |   return ɵɵattributeInterpolate4; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -207,10 +218,13 @@ export function ɵɵattributeInterpolate5( | |||||||
|     v3: any, i3: string, v4: any, suffix: string, sanitizer?: SanitizerFn, |     v3: any, i3: string, v4: any, suffix: string, sanitizer?: SanitizerFn, | ||||||
|     namespace?: string): TsickleIssue1009 { |     namespace?: string): TsickleIssue1009 { | ||||||
|   const index = getSelectedIndex(); |   const index = getSelectedIndex(); | ||||||
|  |   const lView = getLView(); | ||||||
| 
 | 
 | ||||||
|   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 |   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 | ||||||
|   const interpolatedValue = ɵɵinterpolation5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix); |   const interpolatedValue = ɵɵinterpolation5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix); | ||||||
|   ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace); |   if (interpolatedValue !== NO_CHANGE) { | ||||||
|  |     elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace); | ||||||
|  |   } | ||||||
|   return ɵɵattributeInterpolate5; |   return ɵɵattributeInterpolate5; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -254,10 +268,13 @@ export function ɵɵattributeInterpolate6( | |||||||
|     v3: any, i3: string, v4: any, i4: string, v5: any, suffix: string, sanitizer?: SanitizerFn, |     v3: any, i3: string, v4: any, i4: string, v5: any, suffix: string, sanitizer?: SanitizerFn, | ||||||
|     namespace?: string): TsickleIssue1009 { |     namespace?: string): TsickleIssue1009 { | ||||||
|   const index = getSelectedIndex(); |   const index = getSelectedIndex(); | ||||||
|  |   const lView = getLView(); | ||||||
|   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 |   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 | ||||||
|   const interpolatedValue = |   const interpolatedValue = | ||||||
|       ɵɵinterpolation6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix); |       ɵɵinterpolation6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix); | ||||||
|   ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace); |   if (interpolatedValue !== NO_CHANGE) { | ||||||
|  |     elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace); | ||||||
|  |   } | ||||||
|   return ɵɵattributeInterpolate6; |   return ɵɵattributeInterpolate6; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -303,10 +320,13 @@ export function ɵɵattributeInterpolate7( | |||||||
|     v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, suffix: string, |     v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, suffix: string, | ||||||
|     sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 { |     sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 { | ||||||
|   const index = getSelectedIndex(); |   const index = getSelectedIndex(); | ||||||
|  |   const lView = getLView(); | ||||||
|   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 |   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 | ||||||
|   const interpolatedValue = |   const interpolatedValue = | ||||||
|       ɵɵinterpolation7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix); |       ɵɵinterpolation7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix); | ||||||
|   ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace); |   if (interpolatedValue !== NO_CHANGE) { | ||||||
|  |     elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace); | ||||||
|  |   } | ||||||
|   return ɵɵattributeInterpolate7; |   return ɵɵattributeInterpolate7; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -354,10 +374,13 @@ export function ɵɵattributeInterpolate8( | |||||||
|     v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any, |     v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any, | ||||||
|     suffix: string, sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 { |     suffix: string, sanitizer?: SanitizerFn, namespace?: string): TsickleIssue1009 { | ||||||
|   const index = getSelectedIndex(); |   const index = getSelectedIndex(); | ||||||
|  |   const lView = getLView(); | ||||||
|   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 |   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 | ||||||
|   const interpolatedValue = |   const interpolatedValue = | ||||||
|       ɵɵinterpolation8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix); |       ɵɵinterpolation8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix); | ||||||
|   ɵɵelementAttribute(index, attrName, interpolatedValue, sanitizer, namespace); |   if (interpolatedValue !== NO_CHANGE) { | ||||||
|  |     elementAttributeInternal(index, attrName, interpolatedValue, lView, sanitizer, namespace); | ||||||
|  |   } | ||||||
|   return ɵɵattributeInterpolate8; |   return ɵɵattributeInterpolate8; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -391,7 +414,11 @@ export function ɵɵattributeInterpolateV( | |||||||
|     attrName: string, values: any[], sanitizer?: SanitizerFn, |     attrName: string, values: any[], sanitizer?: SanitizerFn, | ||||||
|     namespace?: string): TsickleIssue1009 { |     namespace?: string): TsickleIssue1009 { | ||||||
|   const index = getSelectedIndex(); |   const index = getSelectedIndex(); | ||||||
|  |   const lView = getLView(); | ||||||
|   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 |   // TODO(FW-1340): Refactor to remove the use of other instructions here.
 | ||||||
|   ɵɵelementAttribute(index, attrName, ɵɵinterpolationV(values), sanitizer, namespace); |   const interpolated = ɵɵinterpolationV(values); | ||||||
|  |   if (interpolated !== NO_CHANGE) { | ||||||
|  |     elementAttributeInternal(index, attrName, interpolated, lView, sanitizer, namespace); | ||||||
|  |   } | ||||||
|   return ɵɵattributeInterpolateV; |   return ɵɵattributeInterpolateV; | ||||||
| } | } | ||||||
|  | |||||||
| @ -5,16 +5,14 @@ | |||||||
|  * Use of this source code is governed by an MIT-style license that can be |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {validateAgainstEventAttributes} from '../../sanitization/sanitization'; |  | ||||||
| import {assertDataInRange, assertDefined, assertEqual} from '../../util/assert'; | import {assertDataInRange, assertDefined, assertEqual} from '../../util/assert'; | ||||||
| import {assertHasParent} from '../assert'; | import {assertHasParent} from '../assert'; | ||||||
| import {attachPatchData} from '../context_discovery'; | import {attachPatchData} from '../context_discovery'; | ||||||
| import {registerPostOrderHooks} from '../hooks'; | import {registerPostOrderHooks} from '../hooks'; | ||||||
| import {TAttributes, TNodeFlags, TNodeType} from '../interfaces/node'; | import {TAttributes, TNodeFlags, TNodeType} from '../interfaces/node'; | ||||||
| import {RElement, Renderer3, isProceduralRenderer} from '../interfaces/renderer'; | import {RElement} from '../interfaces/renderer'; | ||||||
| import {SanitizerFn} from '../interfaces/sanitization'; |  | ||||||
| import {StylingContext} from '../interfaces/styling'; | import {StylingContext} from '../interfaces/styling'; | ||||||
| import {BINDING_INDEX, HEADER_OFFSET, LView, QUERIES, RENDERER, TVIEW, T_HOST} from '../interfaces/view'; | import {BINDING_INDEX, HEADER_OFFSET, QUERIES, RENDERER, TVIEW, T_HOST} from '../interfaces/view'; | ||||||
| import {assertNodeType} from '../node_assert'; | import {assertNodeType} from '../node_assert'; | ||||||
| import {appendChild} from '../node_manipulation'; | import {appendChild} from '../node_manipulation'; | ||||||
| import {applyOnCreateInstructions} from '../node_util'; | import {applyOnCreateInstructions} from '../node_util'; | ||||||
| @ -23,14 +21,14 @@ import {getInitialClassNameValue, getInitialStyleStringValue, initializeStaticCo | |||||||
| import {getStylingContextFromLView, hasClassInput, hasStyleInput} from '../styling/util'; | import {getStylingContextFromLView, hasClassInput, hasStyleInput} from '../styling/util'; | ||||||
| import {registerInitialStylingIntoContext} from '../styling_next/instructions'; | import {registerInitialStylingIntoContext} from '../styling_next/instructions'; | ||||||
| import {runtimeIsNewStylingInUse} from '../styling_next/state'; | import {runtimeIsNewStylingInUse} from '../styling_next/state'; | ||||||
| import {NO_CHANGE} from '../tokens'; |  | ||||||
| import {attrsStylingIndexOf, setUpAttributes} from '../util/attrs_utils'; | import {attrsStylingIndexOf, setUpAttributes} from '../util/attrs_utils'; | ||||||
| import {renderStringify} from '../util/misc_utils'; | import {getNativeByTNode, getTNode} from '../util/view_utils'; | ||||||
| import {getNativeByIndex, getNativeByTNode, getTNode} from '../util/view_utils'; | 
 | ||||||
| import {createDirectivesAndLocals, elementCreate, executeContentQueries, getOrCreateTNode, initializeTNodeInputs, setInputsForProperty, setNodeStylingTemplate} from './shared'; | import {createDirectivesAndLocals, elementCreate, executeContentQueries, getOrCreateTNode, initializeTNodeInputs, setInputsForProperty, setNodeStylingTemplate} from './shared'; | ||||||
| import {getActiveDirectiveStylingIndex} from './styling'; | import {getActiveDirectiveStylingIndex} from './styling'; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Create DOM element. The instruction must later be followed by `elementEnd()` call. |  * Create DOM element. The instruction must later be followed by `elementEnd()` call. | ||||||
|  * |  * | ||||||
| @ -197,54 +195,6 @@ export function ɵɵelement( | |||||||
|   ɵɵelementEnd(); |   ɵɵelementEnd(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Updates the value or removes an attribute on an Element. |  | ||||||
|  * |  | ||||||
|  * @param index The index of the element in the data array |  | ||||||
|  * @param name name The name of the attribute. |  | ||||||
|  * @param value value The attribute is removed when value is `null` or `undefined`. |  | ||||||
|  *                  Otherwise the attribute value is set to the stringified value. |  | ||||||
|  * @param sanitizer An optional function used to sanitize the value. |  | ||||||
|  * @param namespace Optional namespace to use when setting the attribute. |  | ||||||
|  * |  | ||||||
|  * @codeGenApi |  | ||||||
|  */ |  | ||||||
| export function ɵɵelementAttribute( |  | ||||||
|     index: number, name: string, value: any, sanitizer?: SanitizerFn | null, |  | ||||||
|     namespace?: string): void { |  | ||||||
|   if (value !== NO_CHANGE) { |  | ||||||
|     const lView = getLView(); |  | ||||||
|     const renderer = lView[RENDERER]; |  | ||||||
|     elementAttributeInternal(index, name, value, lView, renderer, sanitizer, namespace); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export function elementAttributeInternal( |  | ||||||
|     index: number, name: string, value: any, lView: LView, renderer: Renderer3, |  | ||||||
|     sanitizer?: SanitizerFn | null, namespace?: string) { |  | ||||||
|   ngDevMode && validateAgainstEventAttributes(name); |  | ||||||
|   const element = getNativeByIndex(index, lView) as RElement; |  | ||||||
|   if (value == null) { |  | ||||||
|     ngDevMode && ngDevMode.rendererRemoveAttribute++; |  | ||||||
|     isProceduralRenderer(renderer) ? renderer.removeAttribute(element, name, namespace) : |  | ||||||
|                                      element.removeAttribute(name); |  | ||||||
|   } else { |  | ||||||
|     ngDevMode && ngDevMode.rendererSetAttribute++; |  | ||||||
|     const tNode = getTNode(index, lView); |  | ||||||
|     const strValue = |  | ||||||
|         sanitizer == null ? renderStringify(value) : sanitizer(value, tNode.tagName || '', name); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     if (isProceduralRenderer(renderer)) { |  | ||||||
|       renderer.setAttribute(element, name, strValue, namespace); |  | ||||||
|     } else { |  | ||||||
|       namespace ? element.setAttributeNS(namespace, name, strValue) : |  | ||||||
|                   element.setAttribute(name, strValue); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** | /** | ||||||
|  * Assign static attribute values to a host element. |  * Assign static attribute values to a host element. | ||||||
|  * |  * | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ import {Injector} from '../../di'; | |||||||
| import {ErrorHandler} from '../../error_handler'; | import {ErrorHandler} from '../../error_handler'; | ||||||
| import {Type} from '../../interface/type'; | import {Type} from '../../interface/type'; | ||||||
| import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, SchemaMetadata} from '../../metadata/schema'; | import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, SchemaMetadata} from '../../metadata/schema'; | ||||||
| import {validateAgainstEventProperties} from '../../sanitization/sanitization'; | import {validateAgainstEventAttributes, validateAgainstEventProperties} from '../../sanitization/sanitization'; | ||||||
| import {Sanitizer} from '../../sanitization/security'; | import {Sanitizer} from '../../sanitization/security'; | ||||||
| import {assertDataInRange, assertDefined, assertDomNode, assertEqual, assertLessThan, assertNotEqual, assertNotSame} from '../../util/assert'; | import {assertDataInRange, assertDefined, assertDomNode, assertEqual, assertLessThan, assertNotEqual, assertNotSame} from '../../util/assert'; | ||||||
| import {createNamedArrayType} from '../../util/named_array_type'; | import {createNamedArrayType} from '../../util/named_array_type'; | ||||||
| @ -35,7 +35,7 @@ import {initializeStaticContext as initializeStaticStylingContext} from '../styl | |||||||
| import {ANIMATION_PROP_PREFIX, isAnimationProp} from '../styling/util'; | import {ANIMATION_PROP_PREFIX, isAnimationProp} from '../styling/util'; | ||||||
| import {NO_CHANGE} from '../tokens'; | import {NO_CHANGE} from '../tokens'; | ||||||
| import {attrsStylingIndexOf} from '../util/attrs_utils'; | import {attrsStylingIndexOf} from '../util/attrs_utils'; | ||||||
| import {INTERPOLATION_DELIMITER, stringifyForError} from '../util/misc_utils'; | import {INTERPOLATION_DELIMITER, renderStringify, stringifyForError} from '../util/misc_utils'; | ||||||
| import {getLViewParent, getRootContext} from '../util/view_traversal_utils'; | import {getLViewParent, getRootContext} from '../util/view_traversal_utils'; | ||||||
| import {getComponentViewByIndex, getNativeByIndex, getNativeByTNode, getTNode, isComponent, isComponentDef, isContentQueryHost, isLContainer, isRootView, readPatchedLView, resetPreOrderHookFlags, unwrapRNode, viewAttachedToChangeDetector} from '../util/view_utils'; | import {getComponentViewByIndex, getNativeByIndex, getNativeByTNode, getTNode, isComponent, isComponentDef, isContentQueryHost, isLContainer, isRootView, readPatchedLView, resetPreOrderHookFlags, unwrapRNode, viewAttachedToChangeDetector} from '../util/view_utils'; | ||||||
| 
 | 
 | ||||||
| @ -1303,6 +1303,33 @@ function addComponentLogic<T>( | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export function elementAttributeInternal( | ||||||
|  |     index: number, name: string, value: any, lView: LView, sanitizer?: SanitizerFn | null, | ||||||
|  |     namespace?: string) { | ||||||
|  |   ngDevMode && assertNotSame(value, NO_CHANGE as any, 'Incoming value should never be NO_CHANGE.'); | ||||||
|  |   ngDevMode && validateAgainstEventAttributes(name); | ||||||
|  |   const element = getNativeByIndex(index, lView) as RElement; | ||||||
|  |   const renderer = lView[RENDERER]; | ||||||
|  |   if (value == null) { | ||||||
|  |     ngDevMode && ngDevMode.rendererRemoveAttribute++; | ||||||
|  |     isProceduralRenderer(renderer) ? renderer.removeAttribute(element, name, namespace) : | ||||||
|  |                                      element.removeAttribute(name); | ||||||
|  |   } else { | ||||||
|  |     ngDevMode && ngDevMode.rendererSetAttribute++; | ||||||
|  |     const tNode = getTNode(index, lView); | ||||||
|  |     const strValue = | ||||||
|  |         sanitizer == null ? renderStringify(value) : sanitizer(value, tNode.tagName || '', name); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     if (isProceduralRenderer(renderer)) { | ||||||
|  |       renderer.setAttribute(element, name, strValue, namespace); | ||||||
|  |     } else { | ||||||
|  |       namespace ? element.setAttributeNS(namespace, name, strValue) : | ||||||
|  |                   element.setAttribute(name, strValue); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Sets initial input properties on directive instances from attribute data |  * Sets initial input properties on directive instances from attribute data | ||||||
|  * |  * | ||||||
|  | |||||||
| @ -46,7 +46,6 @@ export const angularCoreEnv: {[name: string]: Function} = | |||||||
|        'ɵɵNgOnChangesFeature': r3.ɵɵNgOnChangesFeature, |        'ɵɵNgOnChangesFeature': r3.ɵɵNgOnChangesFeature, | ||||||
|        'ɵɵProvidersFeature': r3.ɵɵProvidersFeature, |        'ɵɵProvidersFeature': r3.ɵɵProvidersFeature, | ||||||
|        'ɵɵInheritDefinitionFeature': r3.ɵɵInheritDefinitionFeature, |        'ɵɵInheritDefinitionFeature': r3.ɵɵInheritDefinitionFeature, | ||||||
|        'ɵɵelementAttribute': r3.ɵɵelementAttribute, |  | ||||||
|        'ɵɵbind': r3.ɵɵbind, |        'ɵɵbind': r3.ɵɵbind, | ||||||
|        'ɵɵcontainer': r3.ɵɵcontainer, |        'ɵɵcontainer': r3.ɵɵcontainer, | ||||||
|        'ɵɵnextContext': r3.ɵɵnextContext, |        'ɵɵnextContext': r3.ɵɵnextContext, | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ | |||||||
| import {NgForOfContext} from '@angular/common'; | import {NgForOfContext} from '@angular/common'; | ||||||
| 
 | 
 | ||||||
| import {ɵɵdefineComponent} from '../../src/render3/definition'; | import {ɵɵdefineComponent} from '../../src/render3/definition'; | ||||||
| import {RenderFlags, ɵɵbind, ɵɵclassMap, ɵɵelement, ɵɵelementAttribute, ɵɵelementEnd, ɵɵelementStart, ɵɵinterpolation1, ɵɵproperty, ɵɵselect, ɵɵstyleMap, ɵɵstyleProp, ɵɵstyling, ɵɵstylingApply, ɵɵtemplate, ɵɵtext, ɵɵtextBinding} from '../../src/render3/index'; | import {RenderFlags, ɵɵattribute, ɵɵclassMap, ɵɵelement, ɵɵelementEnd, ɵɵelementStart, ɵɵinterpolation1, ɵɵproperty, ɵɵselect, ɵɵstyleMap, ɵɵstyleProp, ɵɵstyling, ɵɵstylingApply, ɵɵtemplate, ɵɵtext, ɵɵtextBinding} from '../../src/render3/index'; | ||||||
| import {AttributeMarker} from '../../src/render3/interfaces/node'; | import {AttributeMarker} from '../../src/render3/interfaces/node'; | ||||||
| import {bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl} from '../../src/sanitization/bypass'; | import {bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl} from '../../src/sanitization/bypass'; | ||||||
| import {ɵɵdefaultStyleSanitizer, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl} from '../../src/sanitization/sanitization'; | import {ɵɵdefaultStyleSanitizer, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl} from '../../src/sanitization/sanitization'; | ||||||
| @ -119,16 +119,20 @@ describe('instructions', () => { | |||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   describe('elementAttribute', () => { |   describe('attribute', () => { | ||||||
|     it('should use sanitizer function', () => { |     it('should use sanitizer function', () => { | ||||||
|       const t = new TemplateFixture(createDiv, () => {}, 1); |       const t = new TemplateFixture(createDiv, () => {}, 1, 1); | ||||||
| 
 | 
 | ||||||
|       t.update(() => ɵɵelementAttribute(0, 'title', 'javascript:true', ɵɵsanitizeUrl)); |       t.update(() => { | ||||||
|  |         ɵɵselect(0); | ||||||
|  |         ɵɵattribute('title', 'javascript:true', ɵɵsanitizeUrl); | ||||||
|  |       }); | ||||||
|       expect(t.html).toEqual('<div title="unsafe:javascript:true"></div>'); |       expect(t.html).toEqual('<div title="unsafe:javascript:true"></div>'); | ||||||
| 
 | 
 | ||||||
|       t.update( |       t.update(() => { | ||||||
|           () => ɵɵelementAttribute( |         ɵɵselect(0); | ||||||
|               0, 'title', bypassSanitizationTrustUrl('javascript:true'), ɵɵsanitizeUrl)); |         ɵɵattribute('title', bypassSanitizationTrustUrl('javascript:true'), ɵɵsanitizeUrl); | ||||||
|  |       }); | ||||||
|       expect(t.html).toEqual('<div title="javascript:true"></div>'); |       expect(t.html).toEqual('<div title="javascript:true"></div>'); | ||||||
|       expect(ngDevMode).toHaveProperties({ |       expect(ngDevMode).toHaveProperties({ | ||||||
|         firstTemplatePass: 1, |         firstTemplatePass: 1, | ||||||
| @ -360,99 +364,126 @@ describe('instructions', () => { | |||||||
|   describe('sanitization injection compatibility', () => { |   describe('sanitization injection compatibility', () => { | ||||||
|     it('should work for url sanitization', () => { |     it('should work for url sanitization', () => { | ||||||
|       const s = new LocalMockSanitizer(value => `${value}-sanitized`); |       const s = new LocalMockSanitizer(value => `${value}-sanitized`); | ||||||
|       const t = new TemplateFixture(createAnchor, undefined, 1, 0, null, null, s); |       const t = new TemplateFixture(createAnchor, undefined, 1, 1, null, null, s); | ||||||
|       const inputValue = 'http://foo'; |       const inputValue = 'http://foo'; | ||||||
|       const outputValue = 'http://foo-sanitized'; |       const outputValue = 'http://foo-sanitized'; | ||||||
| 
 | 
 | ||||||
|       t.update(() => ɵɵelementAttribute(0, 'href', inputValue, ɵɵsanitizeUrl)); |       t.update(() => { | ||||||
|  |         ɵɵselect(0); | ||||||
|  |         ɵɵattribute('href', inputValue, ɵɵsanitizeUrl); | ||||||
|  |       }); | ||||||
|       expect(t.html).toEqual(`<a href="${outputValue}"></a>`); |       expect(t.html).toEqual(`<a href="${outputValue}"></a>`); | ||||||
|       expect(s.lastSanitizedValue).toEqual(outputValue); |       expect(s.lastSanitizedValue).toEqual(outputValue); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should bypass url sanitization if marked by the service', () => { |     it('should bypass url sanitization if marked by the service', () => { | ||||||
|       const s = new LocalMockSanitizer(value => ''); |       const s = new LocalMockSanitizer(value => ''); | ||||||
|       const t = new TemplateFixture(createAnchor, undefined, 1, 0, null, null, s); |       const t = new TemplateFixture(createAnchor, undefined, 1, 1, null, null, s); | ||||||
|       const inputValue = s.bypassSecurityTrustUrl('http://foo'); |       const inputValue = s.bypassSecurityTrustUrl('http://foo'); | ||||||
|       const outputValue = 'http://foo'; |       const outputValue = 'http://foo'; | ||||||
| 
 | 
 | ||||||
|       t.update(() => ɵɵelementAttribute(0, 'href', inputValue, ɵɵsanitizeUrl)); |       t.update(() => { | ||||||
|  |         ɵɵselect(0); | ||||||
|  |         ɵɵattribute('href', inputValue, ɵɵsanitizeUrl); | ||||||
|  |       }); | ||||||
|       expect(t.html).toEqual(`<a href="${outputValue}"></a>`); |       expect(t.html).toEqual(`<a href="${outputValue}"></a>`); | ||||||
|       expect(s.lastSanitizedValue).toBeFalsy(); |       expect(s.lastSanitizedValue).toBeFalsy(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should bypass ivy-level url sanitization if a custom sanitizer is used', () => { |     it('should bypass ivy-level url sanitization if a custom sanitizer is used', () => { | ||||||
|       const s = new LocalMockSanitizer(value => ''); |       const s = new LocalMockSanitizer(value => ''); | ||||||
|       const t = new TemplateFixture(createAnchor, undefined, 1, 0, null, null, s); |       const t = new TemplateFixture(createAnchor, undefined, 1, 1, null, null, s); | ||||||
|       const inputValue = bypassSanitizationTrustUrl('http://foo'); |       const inputValue = bypassSanitizationTrustUrl('http://foo'); | ||||||
|       const outputValue = 'http://foo-ivy'; |       const outputValue = 'http://foo-ivy'; | ||||||
| 
 | 
 | ||||||
|       t.update(() => ɵɵelementAttribute(0, 'href', inputValue, ɵɵsanitizeUrl)); |       t.update(() => { | ||||||
|  |         ɵɵselect(0); | ||||||
|  |         ɵɵattribute('href', inputValue, ɵɵsanitizeUrl); | ||||||
|  |       }); | ||||||
|       expect(t.html).toEqual(`<a href="${outputValue}"></a>`); |       expect(t.html).toEqual(`<a href="${outputValue}"></a>`); | ||||||
|       expect(s.lastSanitizedValue).toBeFalsy(); |       expect(s.lastSanitizedValue).toBeFalsy(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should work for style sanitization', () => { |     it('should work for style sanitization', () => { | ||||||
|       const s = new LocalMockSanitizer(value => `color:blue`); |       const s = new LocalMockSanitizer(value => `color:blue`); | ||||||
|       const t = new TemplateFixture(createDiv, undefined, 1, 0, null, null, s); |       const t = new TemplateFixture(createDiv, undefined, 1, 1, null, null, s); | ||||||
|       const inputValue = 'color:red'; |       const inputValue = 'color:red'; | ||||||
|       const outputValue = 'color:blue'; |       const outputValue = 'color:blue'; | ||||||
| 
 | 
 | ||||||
|       t.update(() => ɵɵelementAttribute(0, 'style', inputValue, ɵɵsanitizeStyle)); |       t.update(() => { | ||||||
|  |         ɵɵselect(0); | ||||||
|  |         ɵɵattribute('style', inputValue, ɵɵsanitizeStyle); | ||||||
|  |       }); | ||||||
|       expect(stripStyleWsCharacters(t.html)).toEqual(`<div style="${outputValue}"></div>`); |       expect(stripStyleWsCharacters(t.html)).toEqual(`<div style="${outputValue}"></div>`); | ||||||
|       expect(s.lastSanitizedValue).toEqual(outputValue); |       expect(s.lastSanitizedValue).toEqual(outputValue); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should bypass style sanitization if marked by the service', () => { |     it('should bypass style sanitization if marked by the service', () => { | ||||||
|       const s = new LocalMockSanitizer(value => ''); |       const s = new LocalMockSanitizer(value => ''); | ||||||
|       const t = new TemplateFixture(createDiv, undefined, 1, 0, null, null, s); |       const t = new TemplateFixture(createDiv, undefined, 1, 1, null, null, s); | ||||||
|       const inputValue = s.bypassSecurityTrustStyle('color:maroon'); |       const inputValue = s.bypassSecurityTrustStyle('color:maroon'); | ||||||
|       const outputValue = 'color:maroon'; |       const outputValue = 'color:maroon'; | ||||||
| 
 | 
 | ||||||
|       t.update(() => ɵɵelementAttribute(0, 'style', inputValue, ɵɵsanitizeStyle)); |       t.update(() => { | ||||||
|  |         ɵɵselect(0); | ||||||
|  |         ɵɵattribute('style', inputValue, ɵɵsanitizeStyle); | ||||||
|  |       }); | ||||||
|       expect(stripStyleWsCharacters(t.html)).toEqual(`<div style="${outputValue}"></div>`); |       expect(stripStyleWsCharacters(t.html)).toEqual(`<div style="${outputValue}"></div>`); | ||||||
|       expect(s.lastSanitizedValue).toBeFalsy(); |       expect(s.lastSanitizedValue).toBeFalsy(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should bypass ivy-level style sanitization if a custom sanitizer is used', () => { |     it('should bypass ivy-level style sanitization if a custom sanitizer is used', () => { | ||||||
|       const s = new LocalMockSanitizer(value => ''); |       const s = new LocalMockSanitizer(value => ''); | ||||||
|       const t = new TemplateFixture(createDiv, undefined, 1, 0, null, null, s); |       const t = new TemplateFixture(createDiv, undefined, 1, 1, null, null, s); | ||||||
|       const inputValue = bypassSanitizationTrustStyle('font-family:foo'); |       const inputValue = bypassSanitizationTrustStyle('font-family:foo'); | ||||||
|       const outputValue = 'font-family:foo-ivy'; |       const outputValue = 'font-family:foo-ivy'; | ||||||
| 
 | 
 | ||||||
|       t.update(() => ɵɵelementAttribute(0, 'style', inputValue, ɵɵsanitizeStyle)); |       t.update(() => { | ||||||
|  |         ɵɵselect(0); | ||||||
|  |         ɵɵattribute('style', inputValue, ɵɵsanitizeStyle); | ||||||
|  |       }); | ||||||
|       expect(stripStyleWsCharacters(t.html)).toEqual(`<div style="${outputValue}"></div>`); |       expect(stripStyleWsCharacters(t.html)).toEqual(`<div style="${outputValue}"></div>`); | ||||||
|       expect(s.lastSanitizedValue).toBeFalsy(); |       expect(s.lastSanitizedValue).toBeFalsy(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should work for resourceUrl sanitization', () => { |     it('should work for resourceUrl sanitization', () => { | ||||||
|       const s = new LocalMockSanitizer(value => `${value}-sanitized`); |       const s = new LocalMockSanitizer(value => `${value}-sanitized`); | ||||||
|       const t = new TemplateFixture(createScript, undefined, 1, 0, null, null, s); |       const t = new TemplateFixture(createScript, undefined, 1, 1, null, null, s); | ||||||
|       const inputValue = 'http://resource'; |       const inputValue = 'http://resource'; | ||||||
|       const outputValue = 'http://resource-sanitized'; |       const outputValue = 'http://resource-sanitized'; | ||||||
| 
 | 
 | ||||||
|       t.update(() => ɵɵelementAttribute(0, 'src', inputValue, ɵɵsanitizeResourceUrl)); |       t.update(() => { | ||||||
|  |         ɵɵselect(0); | ||||||
|  |         ɵɵattribute('src', inputValue, ɵɵsanitizeResourceUrl); | ||||||
|  |       }); | ||||||
|       expect(t.html).toEqual(`<script src="${outputValue}"></script>`); |       expect(t.html).toEqual(`<script src="${outputValue}"></script>`); | ||||||
|       expect(s.lastSanitizedValue).toEqual(outputValue); |       expect(s.lastSanitizedValue).toEqual(outputValue); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should bypass resourceUrl sanitization if marked by the service', () => { |     it('should bypass resourceUrl sanitization if marked by the service', () => { | ||||||
|       const s = new LocalMockSanitizer(value => ''); |       const s = new LocalMockSanitizer(value => ''); | ||||||
|       const t = new TemplateFixture(createScript, undefined, 1, 0, null, null, s); |       const t = new TemplateFixture(createScript, undefined, 1, 1, null, null, s); | ||||||
|       const inputValue = s.bypassSecurityTrustResourceUrl('file://all-my-secrets.pdf'); |       const inputValue = s.bypassSecurityTrustResourceUrl('file://all-my-secrets.pdf'); | ||||||
|       const outputValue = 'file://all-my-secrets.pdf'; |       const outputValue = 'file://all-my-secrets.pdf'; | ||||||
| 
 | 
 | ||||||
|       t.update(() => ɵɵelementAttribute(0, 'src', inputValue, ɵɵsanitizeResourceUrl)); |       t.update(() => { | ||||||
|  |         ɵɵselect(0); | ||||||
|  |         ɵɵattribute('src', inputValue, ɵɵsanitizeResourceUrl); | ||||||
|  |       }); | ||||||
|       expect(t.html).toEqual(`<script src="${outputValue}"></script>`); |       expect(t.html).toEqual(`<script src="${outputValue}"></script>`); | ||||||
|       expect(s.lastSanitizedValue).toBeFalsy(); |       expect(s.lastSanitizedValue).toBeFalsy(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should bypass ivy-level resourceUrl sanitization if a custom sanitizer is used', () => { |     it('should bypass ivy-level resourceUrl sanitization if a custom sanitizer is used', () => { | ||||||
|       const s = new LocalMockSanitizer(value => ''); |       const s = new LocalMockSanitizer(value => ''); | ||||||
|       const t = new TemplateFixture(createScript, undefined, 1, 0, null, null, s); |       const t = new TemplateFixture(createScript, undefined, 1, 1, null, null, s); | ||||||
|       const inputValue = bypassSanitizationTrustResourceUrl('file://all-my-secrets.pdf'); |       const inputValue = bypassSanitizationTrustResourceUrl('file://all-my-secrets.pdf'); | ||||||
|       const outputValue = 'file://all-my-secrets.pdf-ivy'; |       const outputValue = 'file://all-my-secrets.pdf-ivy'; | ||||||
| 
 | 
 | ||||||
|       t.update(() => ɵɵelementAttribute(0, 'src', inputValue, ɵɵsanitizeResourceUrl)); |       t.update(() => { | ||||||
|  |         ɵɵselect(0); | ||||||
|  |         ɵɵattribute('src', inputValue, ɵɵsanitizeResourceUrl); | ||||||
|  |       }); | ||||||
|       expect(t.html).toEqual(`<script src="${outputValue}"></script>`); |       expect(t.html).toEqual(`<script src="${outputValue}"></script>`); | ||||||
|       expect(s.lastSanitizedValue).toBeFalsy(); |       expect(s.lastSanitizedValue).toBeFalsy(); | ||||||
|     }); |     }); | ||||||
|  | |||||||
| @ -8,8 +8,8 @@ | |||||||
| 
 | 
 | ||||||
| import {RendererType2} from '../../src/render/api'; | import {RendererType2} from '../../src/render/api'; | ||||||
| import {getLContext} from '../../src/render3/context_discovery'; | import {getLContext} from '../../src/render3/context_discovery'; | ||||||
| import {AttributeMarker, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵproperty} from '../../src/render3/index'; | import {AttributeMarker, ɵɵattribute, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵproperty} from '../../src/render3/index'; | ||||||
| import {ɵɵallocHostVars, ɵɵbind, ɵɵcontainer, ɵɵcontainerRefreshEnd, ɵɵcontainerRefreshStart, ɵɵelement, ɵɵelementAttribute, ɵɵelementEnd, ɵɵelementStart, ɵɵembeddedViewEnd, ɵɵembeddedViewStart, ɵɵprojection, ɵɵprojectionDef, ɵɵselect, ɵɵstyling, ɵɵstylingApply, ɵɵtemplate, ɵɵtext, ɵɵtextBinding} from '../../src/render3/instructions/all'; | import {ɵɵallocHostVars, ɵɵbind, ɵɵcontainer, ɵɵcontainerRefreshEnd, ɵɵcontainerRefreshStart, ɵɵelement, ɵɵelementEnd, ɵɵelementStart, ɵɵembeddedViewEnd, ɵɵembeddedViewStart, ɵɵprojection, ɵɵprojectionDef, ɵɵselect, ɵɵstyling, ɵɵstylingApply, ɵɵtemplate, ɵɵtext, ɵɵtextBinding} from '../../src/render3/instructions/all'; | ||||||
| import {MONKEY_PATCH_KEY_NAME} from '../../src/render3/interfaces/context'; | import {MONKEY_PATCH_KEY_NAME} from '../../src/render3/interfaces/context'; | ||||||
| import {RenderFlags} from '../../src/render3/interfaces/definition'; | import {RenderFlags} from '../../src/render3/interfaces/definition'; | ||||||
| import {RElement, Renderer3, RendererFactory3, domRendererFactory3} from '../../src/render3/interfaces/renderer'; | import {RElement, Renderer3, RendererFactory3, domRendererFactory3} from '../../src/render3/interfaces/renderer'; | ||||||
| @ -286,7 +286,8 @@ describe('component animations', () => { | |||||||
|             ɵɵelement(0, 'div', [AttributeMarker.Bindings, '@fooAnimation']); |             ɵɵelement(0, 'div', [AttributeMarker.Bindings, '@fooAnimation']); | ||||||
|           } |           } | ||||||
|           if (rf & RenderFlags.Update) { |           if (rf & RenderFlags.Update) { | ||||||
|             ɵɵelementAttribute(0, '@fooAnimation', ɵɵbind(ctx.animationValue)); |             ɵɵselect(0); | ||||||
|  |             ɵɵattribute('@fooAnimation', ctx.animationValue); | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								tools/public_api_guard/core/core.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								tools/public_api_guard/core/core.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -818,8 +818,6 @@ export declare function ɵɵdisableBindings(): void; | |||||||
| 
 | 
 | ||||||
| export declare function ɵɵelement(index: number, name: string, attrs?: TAttributes | null, localRefs?: string[] | null): void; | export declare function ɵɵelement(index: number, name: string, attrs?: TAttributes | null, localRefs?: string[] | null): void; | ||||||
| 
 | 
 | ||||||
| export declare function ɵɵelementAttribute(index: number, name: string, value: any, sanitizer?: SanitizerFn | null, namespace?: string): void; |  | ||||||
| 
 |  | ||||||
| export declare function ɵɵelementContainerEnd(): void; | export declare function ɵɵelementContainerEnd(): void; | ||||||
| 
 | 
 | ||||||
| export declare function ɵɵelementContainerStart(index: number, attrs?: TAttributes | null, localRefs?: string[] | null): void; | export declare function ɵɵelementContainerStart(index: number, attrs?: TAttributes | null, localRefs?: string[] | null): void; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user