feat(ivy): add ng-reflect debug text for containers (#27350)
PR Close #27350
This commit is contained in:
		
							parent
							
								
									20cef5078d
								
							
						
					
					
						commit
						1279a503a1
					
				| @ -16,7 +16,6 @@ import {Sanitizer} from '../sanitization/security'; | |||||||
| import {StyleSanitizeFn} from '../sanitization/style_sanitizer'; | import {StyleSanitizeFn} from '../sanitization/style_sanitizer'; | ||||||
| import {Type} from '../type'; | import {Type} from '../type'; | ||||||
| import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../util/ng_reflect'; | import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../util/ng_reflect'; | ||||||
| 
 |  | ||||||
| import {assertDataInRange, assertDefined, assertEqual, assertHasParent, assertLessThan, assertNotEqual, assertPreviousIsParent} from './assert'; | import {assertDataInRange, assertDefined, assertEqual, assertHasParent, assertLessThan, assertNotEqual, assertPreviousIsParent} from './assert'; | ||||||
| import {bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4} from './bindings'; | import {bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4} from './bindings'; | ||||||
| import {attachPatchData, getComponentViewByInstance} from './context_discovery'; | import {attachPatchData, getComponentViewByInstance} from './context_discovery'; | ||||||
| @ -30,7 +29,7 @@ import {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, Pro | |||||||
| import {PlayerFactory} from './interfaces/player'; | import {PlayerFactory} from './interfaces/player'; | ||||||
| import {CssSelectorList, NG_PROJECT_AS_ATTR_NAME} from './interfaces/projection'; | import {CssSelectorList, NG_PROJECT_AS_ATTR_NAME} from './interfaces/projection'; | ||||||
| import {LQueries} from './interfaces/query'; | import {LQueries} from './interfaces/query'; | ||||||
| import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, RendererFactory3, isProceduralRenderer} from './interfaces/renderer'; | import {ProceduralRenderer3, RComment, RElement, RText, Renderer3, RendererFactory3, isProceduralRenderer} from './interfaces/renderer'; | ||||||
| import {SanitizerFn} from './interfaces/sanitization'; | import {SanitizerFn} from './interfaces/sanitization'; | ||||||
| import {StylingIndex} from './interfaces/styling'; | import {StylingIndex} from './interfaces/styling'; | ||||||
| import {BINDING_INDEX, CLEANUP, CONTAINER_INDEX, CONTENT_QUERIES, CONTEXT, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, HOST_NODE, INJECTOR, LView, LViewFlags, NEXT, OpaqueViewState, PARENT, QUERIES, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TAIL, TVIEW, TView} from './interfaces/view'; | import {BINDING_INDEX, CLEANUP, CONTAINER_INDEX, CONTENT_QUERIES, CONTEXT, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, HOST_NODE, INJECTOR, LView, LViewFlags, NEXT, OpaqueViewState, PARENT, QUERIES, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TAIL, TVIEW, TView} from './interfaces/view'; | ||||||
| @ -957,8 +956,10 @@ export function elementProperty<T>( | |||||||
|   if (inputData && (dataValue = inputData[propName])) { |   if (inputData && (dataValue = inputData[propName])) { | ||||||
|     setInputsForProperty(lView, dataValue, value); |     setInputsForProperty(lView, dataValue, value); | ||||||
|     if (isComponent(tNode)) markDirtyIfOnPush(lView, index + HEADER_OFFSET); |     if (isComponent(tNode)) markDirtyIfOnPush(lView, index + HEADER_OFFSET); | ||||||
|     if (ngDevMode && tNode.type === TNodeType.Element) { |     if (ngDevMode) { | ||||||
|       setNgReflectProperties(lView, element as RElement, propName, value); |       if (tNode.type === TNodeType.Element || tNode.type === TNodeType.Container) { | ||||||
|  |         setNgReflectProperties(lView, element, tNode.type, propName, value); | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } else if (tNode.type === TNodeType.Element) { |   } else if (tNode.type === TNodeType.Element) { | ||||||
|     const renderer = lView[RENDERER]; |     const renderer = lView[RENDERER]; | ||||||
| @ -1031,12 +1032,23 @@ function setInputsForProperty(lView: LView, inputs: PropertyAliasValue, value: a | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function setNgReflectProperties(lView: LView, element: RElement, propName: string, value: any) { | function setNgReflectProperties( | ||||||
|  |     lView: LView, element: RElement | RComment, type: TNodeType, propName: string, value: any) { | ||||||
|   const renderer = lView[RENDERER]; |   const renderer = lView[RENDERER]; | ||||||
|   const attrName = normalizeDebugBindingName(propName); |   const attrName = normalizeDebugBindingName(propName); | ||||||
|   const debugValue = normalizeDebugBindingValue(value); |   const debugValue = normalizeDebugBindingValue(value); | ||||||
|   isProceduralRenderer(renderer) ? renderer.setAttribute(element, attrName, debugValue) : |   if (type === TNodeType.Element) { | ||||||
|                                    element.setAttribute(attrName, debugValue); |     isProceduralRenderer(renderer) ? | ||||||
|  |         renderer.setAttribute((element as RElement), attrName, debugValue) : | ||||||
|  |         (element as RElement).setAttribute(attrName, debugValue); | ||||||
|  |   } else if (value !== undefined) { | ||||||
|  |     const value = `bindings=${JSON.stringify({[attrName]: debugValue}, null, 2)}`; | ||||||
|  |     if (isProceduralRenderer(renderer)) { | ||||||
|  |       renderer.setValue((element as RComment), value); | ||||||
|  |     } else { | ||||||
|  |       (element as RComment).textContent = value; | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -83,7 +83,7 @@ export interface ProceduralRenderer3 { | |||||||
|       flags?: RendererStyleFlags2|RendererStyleFlags3): void; |       flags?: RendererStyleFlags2|RendererStyleFlags3): void; | ||||||
|   removeStyle(el: RElement, style: string, flags?: RendererStyleFlags2|RendererStyleFlags3): void; |   removeStyle(el: RElement, style: string, flags?: RendererStyleFlags2|RendererStyleFlags3): void; | ||||||
|   setProperty(el: RElement, name: string, value: any): void; |   setProperty(el: RElement, name: string, value: any): void; | ||||||
|   setValue(node: RText, value: string): void; |   setValue(node: RText|RComment, value: string): void; | ||||||
| 
 | 
 | ||||||
|   // TODO(misko): Deprecate in favor of addEventListener/removeEventListener
 |   // TODO(misko): Deprecate in favor of addEventListener/removeEventListener
 | ||||||
|   listen(target: RNode, eventName: string, callback: (event: any) => boolean | void): () => void; |   listen(target: RNode, eventName: string, callback: (event: any) => boolean | void): () => void; | ||||||
| @ -152,7 +152,7 @@ export interface RDomTokenList { | |||||||
| 
 | 
 | ||||||
| export interface RText extends RNode { textContent: string|null; } | export interface RText extends RNode { textContent: string|null; } | ||||||
| 
 | 
 | ||||||
| export interface RComment extends RNode {} | export interface RComment extends RNode { textContent: string|null; } | ||||||
| 
 | 
 | ||||||
| // Note: This hack is necessary so we don't erroneously get a circular dependency
 | // Note: This hack is necessary so we don't erroneously get a circular dependency
 | ||||||
| // failure based on types.
 | // failure based on types.
 | ||||||
|  | |||||||
| @ -1688,7 +1688,7 @@ function declareTests(config?: {useJit: boolean}) { | |||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     describe('logging property updates', () => { |     describe('logging property updates', () => { | ||||||
|       fixmeIvy('FW-664: ng-reflect-* is not supported') |       fixmeIvy('FW-587: Inputs with aliases in component decorators don\'t work') | ||||||
|           .it('should reflect property values as attributes', () => { |           .it('should reflect property values as attributes', () => { | ||||||
|             TestBed.configureTestingModule({declarations: [MyComp, MyDir]}); |             TestBed.configureTestingModule({declarations: [MyComp, MyDir]}); | ||||||
|             const template = '<div>' + |             const template = '<div>' + | ||||||
| @ -1712,21 +1712,19 @@ function declareTests(config?: {useJit: boolean}) { | |||||||
|         expect(getDOM().getInnerHTML(fixture.nativeElement)).toContain('ng-reflect-test_="hello"'); |         expect(getDOM().getInnerHTML(fixture.nativeElement)).toContain('ng-reflect-test_="hello"'); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       fixmeIvy('FW-664: ng-reflect-* is not supported') |       it('should reflect property values on template comments', () => { | ||||||
|           .it('should reflect property values on template comments', () => { |         const fixture = | ||||||
|             const fixture = |             TestBed.configureTestingModule({declarations: [MyComp]}) | ||||||
|                 TestBed.configureTestingModule({declarations: [MyComp]}) |                 .overrideComponent( | ||||||
|                     .overrideComponent( |                     MyComp, {set: {template: '<ng-template [ngIf]="ctxBoolProp"></ng-template>'}}) | ||||||
|                         MyComp, |                 .createComponent(MyComp); | ||||||
|                         {set: {template: '<ng-template [ngIf]="ctxBoolProp"></ng-template>'}}) |  | ||||||
|                     .createComponent(MyComp); |  | ||||||
| 
 | 
 | ||||||
|             fixture.componentInstance.ctxBoolProp = true; |         fixture.componentInstance.ctxBoolProp = true; | ||||||
|             fixture.detectChanges(); |         fixture.detectChanges(); | ||||||
| 
 | 
 | ||||||
|             expect(getDOM().getInnerHTML(fixture.nativeElement)) |         expect(getDOM().getInnerHTML(fixture.nativeElement)) | ||||||
|                 .toContain('"ng\-reflect\-ng\-if"\: "true"'); |             .toContain('"ng\-reflect\-ng\-if"\: "true"'); | ||||||
|           }); |       }); | ||||||
| 
 | 
 | ||||||
|       // also affected by FW-587: Inputs with aliases in component decorators don't work
 |       // also affected by FW-587: Inputs with aliases in component decorators don't work
 | ||||||
|       fixmeIvy('FW-664: ng-reflect-* is not supported') |       fixmeIvy('FW-664: ng-reflect-* is not supported') | ||||||
|  | |||||||
| @ -273,16 +273,19 @@ export function toHtml<T>(componentOrElement: T | RElement, keepNgReflect = fals | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (element) { |   if (element) { | ||||||
|     let html = stringifyElement(element) |     let html = stringifyElement(element); | ||||||
|                    .replace(/^<div host="">(.*)<\/div>$/, '$1') | 
 | ||||||
|                    .replace(/^<div fixture="mark">(.*)<\/div>$/, '$1') |  | ||||||
|                    .replace(/^<div host="mark">(.*)<\/div>$/, '$1') |  | ||||||
|                    .replace(' style=""', '') |  | ||||||
|                    .replace(/<!--container-->/g, '') |  | ||||||
|                    .replace(/<!--ng-container-->/g, ''); |  | ||||||
|     if (!keepNgReflect) { |     if (!keepNgReflect) { | ||||||
|       html = html.replace(/\sng-reflect-\S*="[^"]*"/g, ''); |       html = html.replace(/\sng-reflect-\S*="[^"]*"/g, '') | ||||||
|  |                  .replace(/<!--bindings=\{(\W.*\W\s*)?\}-->/g, ''); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     html = html.replace(/^<div host="">(.*)<\/div>$/, '$1') | ||||||
|  |                .replace(/^<div fixture="mark">(.*)<\/div>$/, '$1') | ||||||
|  |                .replace(/^<div host="mark">(.*)<\/div>$/, '$1') | ||||||
|  |                .replace(' style=""', '') | ||||||
|  |                .replace(/<!--container-->/g, '') | ||||||
|  |                .replace(/<!--ng-container-->/g, ''); | ||||||
|     return html; |     return html; | ||||||
|   } else { |   } else { | ||||||
|     return ''; |     return ''; | ||||||
|  | |||||||
| @ -131,16 +131,15 @@ let lastCreatedRenderer: Renderer2; | |||||||
|               checkSetters(fixture.componentRef, fixture.debugElement.children[0].nativeElement); |               checkSetters(fixture.componentRef, fixture.debugElement.children[0].nativeElement); | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|     fixmeIvy('#FW-664 ng-reflect-* is not supported') |     it('should update any template comment property/attributes', () => { | ||||||
|         .it('should update any template comment property/attributes', () => { |       const fixture = | ||||||
|           const fixture = |           TestBed.overrideTemplate(MyComp2, '<ng-container *ngIf="ctxBoolProp"></ng-container>') | ||||||
|               TestBed.overrideTemplate(MyComp2, '<ng-container *ngIf="ctxBoolProp"></ng-container>') |               .createComponent(MyComp2); | ||||||
|                   .createComponent(MyComp2); |       fixture.componentInstance.ctxBoolProp = true; | ||||||
|           fixture.componentInstance.ctxBoolProp = true; |       fixture.detectChanges(); | ||||||
|           fixture.detectChanges(); |       const el = getRenderElement(fixture.nativeElement); | ||||||
|           const el = getRenderElement(fixture.nativeElement); |       expect(getDOM().getInnerHTML(el)).toContain('"ng-reflect-ng-if": "true"'); | ||||||
|           expect(getDOM().getInnerHTML(el)).toContain('"ng-reflect-ng-if": "true"'); |     }); | ||||||
|         }); |  | ||||||
| 
 | 
 | ||||||
|     it('should add and remove fragments', () => { |     it('should add and remove fragments', () => { | ||||||
|       const fixture = |       const fixture = | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user