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 {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<T>(
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 = '<div>' +
|
||||
|
@ -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: '<ng-template [ngIf]="ctxBoolProp"></ng-template>'}})
|
||||
.createComponent(MyComp);
|
||||
it('should reflect property values on template comments', () => {
|
||||
const fixture =
|
||||
TestBed.configureTestingModule({declarations: [MyComp]})
|
||||
.overrideComponent(
|
||||
MyComp, {set: {template: '<ng-template [ngIf]="ctxBoolProp"></ng-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')
|
||||
|
|
|
@ -273,16 +273,19 @@ export function toHtml<T>(componentOrElement: T | RElement, keepNgReflect = fals
|
|||
}
|
||||
|
||||
if (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, '');
|
||||
let html = stringifyElement(element);
|
||||
|
||||
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;
|
||||
} else {
|
||||
return '';
|
||||
|
|
|
@ -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, '<ng-container *ngIf="ctxBoolProp"></ng-container>')
|
||||
.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, '<ng-container *ngIf="ctxBoolProp"></ng-container>')
|
||||
.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 =
|
||||
|
|
Loading…
Reference in New Issue