From 1279a503a16e9793bc79388eca9dbebeebef197d Mon Sep 17 00:00:00 2001 From: Olivier Combe Date: Thu, 29 Nov 2018 16:39:43 +0100 Subject: [PATCH] feat(ivy): add ng-reflect debug text for containers (#27350) PR Close #27350 --- packages/core/src/render3/instructions.ts | 26 ++++++++++++++----- .../core/src/render3/interfaces/renderer.ts | 4 +-- packages/core/test/linker/integration_spec.ts | 26 +++++++++---------- packages/core/test/render3/render_util.ts | 19 ++++++++------ .../worker/renderer_v2_integration_spec.ts | 19 +++++++------- 5 files changed, 53 insertions(+), 41 deletions(-) diff --git a/packages/core/src/render3/instructions.ts b/packages/core/src/render3/instructions.ts index eadc65eca3..a6abc8d5f4 100644 --- a/packages/core/src/render3/instructions.ts +++ b/packages/core/src/render3/instructions.ts @@ -16,7 +16,6 @@ import {Sanitizer} from '../sanitization/security'; import {StyleSanitizeFn} from '../sanitization/style_sanitizer'; import {Type} from '../type'; import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../util/ng_reflect'; - import {assertDataInRange, assertDefined, assertEqual, assertHasParent, assertLessThan, assertNotEqual, assertPreviousIsParent} from './assert'; import {bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4} from './bindings'; import {attachPatchData, getComponentViewByInstance} from './context_discovery'; @@ -30,7 +29,7 @@ import {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, Pro import {PlayerFactory} from './interfaces/player'; import {CssSelectorList, NG_PROJECT_AS_ATTR_NAME} from './interfaces/projection'; 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 {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'; @@ -957,8 +956,10 @@ export function elementProperty( if (inputData && (dataValue = inputData[propName])) { setInputsForProperty(lView, dataValue, value); if (isComponent(tNode)) markDirtyIfOnPush(lView, index + HEADER_OFFSET); - if (ngDevMode && tNode.type === TNodeType.Element) { - setNgReflectProperties(lView, element as RElement, propName, value); + if (ngDevMode) { + if (tNode.type === TNodeType.Element || tNode.type === TNodeType.Container) { + setNgReflectProperties(lView, element, tNode.type, propName, value); + } } } else if (tNode.type === TNodeType.Element) { 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 attrName = normalizeDebugBindingName(propName); const debugValue = normalizeDebugBindingValue(value); - isProceduralRenderer(renderer) ? renderer.setAttribute(element, attrName, debugValue) : - element.setAttribute(attrName, debugValue); + if (type === TNodeType.Element) { + 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; + } + } } /** diff --git a/packages/core/src/render3/interfaces/renderer.ts b/packages/core/src/render3/interfaces/renderer.ts index 38a3247b49..c54ee5326b 100644 --- a/packages/core/src/render3/interfaces/renderer.ts +++ b/packages/core/src/render3/interfaces/renderer.ts @@ -83,7 +83,7 @@ export interface ProceduralRenderer3 { flags?: RendererStyleFlags2|RendererStyleFlags3): void; removeStyle(el: RElement, style: string, flags?: RendererStyleFlags2|RendererStyleFlags3): 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 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 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 // failure based on types. diff --git a/packages/core/test/linker/integration_spec.ts b/packages/core/test/linker/integration_spec.ts index faf7c82b25..e91675213d 100644 --- a/packages/core/test/linker/integration_spec.ts +++ b/packages/core/test/linker/integration_spec.ts @@ -1688,7 +1688,7 @@ function declareTests(config?: {useJit: boolean}) { }); 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', () => { TestBed.configureTestingModule({declarations: [MyComp, MyDir]}); const template = '
' + @@ -1712,21 +1712,19 @@ function declareTests(config?: {useJit: boolean}) { 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', () => { - const fixture = - TestBed.configureTestingModule({declarations: [MyComp]}) - .overrideComponent( - MyComp, - {set: {template: ''}}) - .createComponent(MyComp); + it('should reflect property values on template comments', () => { + const fixture = + TestBed.configureTestingModule({declarations: [MyComp]}) + .overrideComponent( + MyComp, {set: {template: ''}}) + .createComponent(MyComp); - fixture.componentInstance.ctxBoolProp = true; - fixture.detectChanges(); + fixture.componentInstance.ctxBoolProp = true; + fixture.detectChanges(); - expect(getDOM().getInnerHTML(fixture.nativeElement)) - .toContain('"ng\-reflect\-ng\-if"\: "true"'); - }); + expect(getDOM().getInnerHTML(fixture.nativeElement)) + .toContain('"ng\-reflect\-ng\-if"\: "true"'); + }); // also affected by FW-587: Inputs with aliases in component decorators don't work fixmeIvy('FW-664: ng-reflect-* is not supported') diff --git a/packages/core/test/render3/render_util.ts b/packages/core/test/render3/render_util.ts index 837d5174d2..332ecee319 100644 --- a/packages/core/test/render3/render_util.ts +++ b/packages/core/test/render3/render_util.ts @@ -273,16 +273,19 @@ export function toHtml(componentOrElement: T | RElement, keepNgReflect = fals } if (element) { - let html = stringifyElement(element) - .replace(/^
(.*)<\/div>$/, '$1') - .replace(/^
(.*)<\/div>$/, '$1') - .replace(/^
(.*)<\/div>$/, '$1') - .replace(' style=""', '') - .replace(//g, '') - .replace(//g, ''); + let html = stringifyElement(element); + if (!keepNgReflect) { - html = html.replace(/\sng-reflect-\S*="[^"]*"/g, ''); + html = html.replace(/\sng-reflect-\S*="[^"]*"/g, '') + .replace(//g, ''); } + + html = html.replace(/^
(.*)<\/div>$/, '$1') + .replace(/^
(.*)<\/div>$/, '$1') + .replace(/^
(.*)<\/div>$/, '$1') + .replace(' style=""', '') + .replace(//g, '') + .replace(//g, ''); return html; } else { return ''; diff --git a/packages/platform-webworker/test/web_workers/worker/renderer_v2_integration_spec.ts b/packages/platform-webworker/test/web_workers/worker/renderer_v2_integration_spec.ts index e2afac213a..7bb1f66920 100644 --- a/packages/platform-webworker/test/web_workers/worker/renderer_v2_integration_spec.ts +++ b/packages/platform-webworker/test/web_workers/worker/renderer_v2_integration_spec.ts @@ -131,16 +131,15 @@ let lastCreatedRenderer: Renderer2; checkSetters(fixture.componentRef, fixture.debugElement.children[0].nativeElement); }); - fixmeIvy('#FW-664 ng-reflect-* is not supported') - .it('should update any template comment property/attributes', () => { - const fixture = - TestBed.overrideTemplate(MyComp2, '') - .createComponent(MyComp2); - fixture.componentInstance.ctxBoolProp = true; - fixture.detectChanges(); - const el = getRenderElement(fixture.nativeElement); - expect(getDOM().getInnerHTML(el)).toContain('"ng-reflect-ng-if": "true"'); - }); + it('should update any template comment property/attributes', () => { + const fixture = + TestBed.overrideTemplate(MyComp2, '') + .createComponent(MyComp2); + fixture.componentInstance.ctxBoolProp = true; + fixture.detectChanges(); + const el = getRenderElement(fixture.nativeElement); + expect(getDOM().getInnerHTML(el)).toContain('"ng-reflect-ng-if": "true"'); + }); it('should add and remove fragments', () => { const fixture =