mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
refactor(core): drop render-related perf counters (#60200)
It looks like we are not getting enough value from having those counters. This is an exploratory PR to see if thsoe could be removed. PR Close #60200
This commit is contained in:
parent
f8bf888d5d
commit
39b324de67
14 changed files with 3 additions and 267 deletions
|
|
@ -738,7 +738,6 @@ export function createContainerRef(
|
|||
*/
|
||||
function insertAnchorNode(hostLView: LView, hostTNode: TNode): RComment {
|
||||
const renderer = hostLView[RENDERER];
|
||||
ngDevMode && ngDevMode.rendererCreateComment++;
|
||||
const commentNode = renderer.createComment(ngDevMode ? 'container' : '');
|
||||
|
||||
const hostNative = getNativeByTNode(hostTNode, hostLView)!;
|
||||
|
|
|
|||
|
|
@ -14,18 +14,14 @@ import {setUpAttributes} from './util/attrs_utils';
|
|||
import {TNode} from './interfaces/node';
|
||||
|
||||
export function createTextNode(renderer: Renderer, value: string): RText {
|
||||
ngDevMode && ngDevMode.rendererCreateTextNode++;
|
||||
ngDevMode && ngDevMode.rendererSetText++;
|
||||
return renderer.createText(value);
|
||||
}
|
||||
|
||||
export function updateTextNode(renderer: Renderer, rNode: RText, value: string): void {
|
||||
ngDevMode && ngDevMode.rendererSetText++;
|
||||
renderer.setValue(rNode, value);
|
||||
}
|
||||
|
||||
export function createCommentNode(renderer: Renderer, value: string): RComment {
|
||||
ngDevMode && ngDevMode.rendererCreateComment++;
|
||||
return renderer.createComment(escapeCommentText(value));
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +37,6 @@ export function createElementNode(
|
|||
name: string,
|
||||
namespace: string | null,
|
||||
): RElement {
|
||||
ngDevMode && ngDevMode.rendererCreateElement++;
|
||||
return renderer.createElement(name, namespace);
|
||||
}
|
||||
|
||||
|
|
@ -56,12 +51,10 @@ export function nativeInsertBefore(
|
|||
beforeNode: RNode | null,
|
||||
isMove: boolean,
|
||||
): void {
|
||||
ngDevMode && ngDevMode.rendererInsertBefore++;
|
||||
renderer.insertBefore(parent, child, beforeNode, isMove);
|
||||
}
|
||||
|
||||
export function nativeAppendChild(renderer: Renderer, parent: RElement, child: RNode): void {
|
||||
ngDevMode && ngDevMode.rendererAppendChild++;
|
||||
ngDevMode && assertDefined(parent, 'parent node must be defined');
|
||||
renderer.appendChild(parent, child);
|
||||
}
|
||||
|
|
@ -90,7 +83,6 @@ export function nativeAppendOrInsertBefore(
|
|||
* @param isHostElement A flag indicating if a node to be removed is a host of a component.
|
||||
*/
|
||||
export function nativeRemoveNode(renderer: Renderer, rNode: RNode, isHostElement?: boolean): void {
|
||||
ngDevMode && ngDevMode.rendererRemoveNode++;
|
||||
renderer.removeChild(null, rNode, isHostElement);
|
||||
}
|
||||
|
||||
|
|
@ -116,7 +108,6 @@ export function clearElementContents(rElement: RElement): void {
|
|||
function writeDirectStyle(renderer: Renderer, element: RElement, newValue: string) {
|
||||
ngDevMode && assertString(newValue, "'newValue' should be a string");
|
||||
renderer.setAttribute(element, 'style', newValue);
|
||||
ngDevMode && ngDevMode.rendererSetStyle++;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -137,7 +128,6 @@ function writeDirectClass(renderer: Renderer, element: RElement, newValue: strin
|
|||
} else {
|
||||
renderer.setAttribute(element, 'class', newValue);
|
||||
}
|
||||
ngDevMode && ngDevMode.rendererSetClassName++;
|
||||
}
|
||||
|
||||
/** Sets up the static DOM attributes on an `RNode`. */
|
||||
|
|
|
|||
|
|
@ -258,7 +258,6 @@ export function applyMutableOpCodes(
|
|||
if (typeof opCode == 'string') {
|
||||
const textNodeIndex = mutableOpCodes[++i] as number;
|
||||
if (lView[textNodeIndex] === null) {
|
||||
ngDevMode && ngDevMode.rendererCreateTextNode++;
|
||||
ngDevMode && assertIndexInRange(lView, textNodeIndex);
|
||||
lView[textNodeIndex] = _locateOrCreateNode(lView, textNodeIndex, opCode, Node.TEXT_NODE);
|
||||
}
|
||||
|
|
@ -344,7 +343,6 @@ export function applyMutableOpCodes(
|
|||
'string',
|
||||
`Expected "${commentValue}" to be a comment node value`,
|
||||
);
|
||||
ngDevMode && ngDevMode.rendererCreateComment++;
|
||||
ngDevMode && assertIndexInExpandoRange(lView, commentNodeIndex);
|
||||
const commentRNode = (lView[commentNodeIndex] = _locateOrCreateNode(
|
||||
lView,
|
||||
|
|
@ -367,7 +365,6 @@ export function applyMutableOpCodes(
|
|||
`Expected "${tagName}" to be an element node tag name`,
|
||||
);
|
||||
|
||||
ngDevMode && ngDevMode.rendererCreateElement++;
|
||||
ngDevMode && assertIndexInExpandoRange(lView, elementNodeIndex);
|
||||
const elementRNode = (lView[elementNodeIndex] = _locateOrCreateNode(
|
||||
lView,
|
||||
|
|
|
|||
|
|
@ -220,7 +220,6 @@ export function listenerInternal(
|
|||
listenerFn = wrapListener(tNode, lView, context, listenerFn);
|
||||
stashEventListener(target as RElement, eventName, listenerFn);
|
||||
const cleanupFn = renderer.listen(target as RElement, eventName, listenerFn);
|
||||
ngDevMode && ngDevMode.rendererAddEventListener++;
|
||||
|
||||
lCleanup.push(listenerFn, cleanupFn);
|
||||
tCleanup && tCleanup.push(eventName, idxOrTargetGetter, lCleanupIndex, lCleanupIndex + 1);
|
||||
|
|
|
|||
|
|
@ -269,7 +269,6 @@ export function elementPropertyInternal<T>(
|
|||
if (!isPropertyValid(element, propName, tNode.value, tView.schemas)) {
|
||||
handleUnknownPropertyError(propName, tNode.value, tNode.type, lView);
|
||||
}
|
||||
ngDevMode.rendererSetProperty++;
|
||||
}
|
||||
|
||||
// It is assumed that the sanitizer is only added when the compiler determines that the
|
||||
|
|
@ -493,10 +492,8 @@ export function setElementAttribute(
|
|||
sanitizer: SanitizerFn | null | undefined,
|
||||
) {
|
||||
if (value == null) {
|
||||
ngDevMode && ngDevMode.rendererRemoveAttribute++;
|
||||
renderer.removeAttribute(element, name, namespace);
|
||||
} else {
|
||||
ngDevMode && ngDevMode.rendererSetAttribute++;
|
||||
const strValue =
|
||||
sanitizer == null ? renderStringify(value) : sanitizer(value, tagName || '', name);
|
||||
|
||||
|
|
|
|||
|
|
@ -138,7 +138,6 @@ function applyToElementOrContainer(
|
|||
} else if (action === WalkTNodeTreeAction.Detach) {
|
||||
nativeRemoveNode(renderer, rNode, isComponent);
|
||||
} else if (action === WalkTNodeTreeAction.Destroy) {
|
||||
ngDevMode && ngDevMode.rendererDestroyNode++;
|
||||
renderer.destroyNode!(rNode);
|
||||
}
|
||||
if (lContainer != null) {
|
||||
|
|
@ -321,7 +320,6 @@ function cleanUpView(tView: TView, lView: LView): void {
|
|||
processCleanups(tView, lView);
|
||||
// For component views only, the local renderer is destroyed at clean up time.
|
||||
if (lView[TVIEW].type === TViewType.Component) {
|
||||
ngDevMode && ngDevMode.rendererDestroy++;
|
||||
lView[RENDERER].destroy();
|
||||
}
|
||||
|
||||
|
|
@ -977,16 +975,13 @@ export function applyStyling(
|
|||
if (isClassBased) {
|
||||
// We actually want JS true/false here because any truthy value should add the class
|
||||
if (!value) {
|
||||
ngDevMode && ngDevMode.rendererRemoveClass++;
|
||||
renderer.removeClass(rNode, prop);
|
||||
} else {
|
||||
ngDevMode && ngDevMode.rendererAddClass++;
|
||||
renderer.addClass(rNode, prop);
|
||||
}
|
||||
} else {
|
||||
let flags = prop.indexOf('-') === -1 ? undefined : (RendererStyleFlags2.DashCase as number);
|
||||
if (value == null /** || value === undefined */) {
|
||||
ngDevMode && ngDevMode.rendererRemoveStyle++;
|
||||
renderer.removeStyle(rNode, prop, flags);
|
||||
} else {
|
||||
// A value is important if it ends with `!important`. The style
|
||||
|
|
@ -999,7 +994,6 @@ export function applyStyling(
|
|||
flags! |= RendererStyleFlags2.Important;
|
||||
}
|
||||
|
||||
ngDevMode && ngDevMode.rendererSetStyle++;
|
||||
renderer.setStyle(rNode, prop, value, flags);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,14 +57,12 @@ export function setUpAttributes(renderer: Renderer, native: RElement, attrs: TAt
|
|||
const namespaceURI = attrs[i++] as string;
|
||||
const attrName = attrs[i++] as string;
|
||||
const attrVal = attrs[i++] as string;
|
||||
ngDevMode && ngDevMode.rendererSetAttribute++;
|
||||
renderer.setAttribute(native, attrName, attrVal, namespaceURI);
|
||||
} else {
|
||||
// attrName is string;
|
||||
const attrName = value as string;
|
||||
const attrVal = attrs[++i];
|
||||
// Standard attributes
|
||||
ngDevMode && ngDevMode.rendererSetAttribute++;
|
||||
if (isAnimationProp(attrName)) {
|
||||
renderer.setProperty(native, attrName, attrVal);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -30,25 +30,6 @@ declare global {
|
|||
firstCreatePass: number;
|
||||
tNode: number;
|
||||
tView: number;
|
||||
rendererCreateTextNode: number;
|
||||
rendererSetText: number;
|
||||
rendererCreateElement: number;
|
||||
rendererAddEventListener: number;
|
||||
rendererSetAttribute: number;
|
||||
rendererRemoveAttribute: number;
|
||||
rendererSetProperty: number;
|
||||
rendererSetClassName: number;
|
||||
rendererAddClass: number;
|
||||
rendererRemoveClass: number;
|
||||
rendererSetStyle: number;
|
||||
rendererRemoveStyle: number;
|
||||
rendererDestroy: number;
|
||||
rendererDestroyNode: number;
|
||||
rendererMoveNode: number;
|
||||
rendererRemoveNode: number;
|
||||
rendererAppendChild: number;
|
||||
rendererInsertBefore: number;
|
||||
rendererCreateComment: number;
|
||||
hydratedNodes: number;
|
||||
hydratedComponents: number;
|
||||
dehydratedViewsRemoved: number;
|
||||
|
|
@ -65,25 +46,6 @@ export function ngDevModeResetPerfCounters(): NgDevModePerfCounters {
|
|||
firstCreatePass: 0,
|
||||
tNode: 0,
|
||||
tView: 0,
|
||||
rendererCreateTextNode: 0,
|
||||
rendererSetText: 0,
|
||||
rendererCreateElement: 0,
|
||||
rendererAddEventListener: 0,
|
||||
rendererSetAttribute: 0,
|
||||
rendererRemoveAttribute: 0,
|
||||
rendererSetProperty: 0,
|
||||
rendererSetClassName: 0,
|
||||
rendererAddClass: 0,
|
||||
rendererRemoveClass: 0,
|
||||
rendererSetStyle: 0,
|
||||
rendererRemoveStyle: 0,
|
||||
rendererDestroy: 0,
|
||||
rendererDestroyNode: 0,
|
||||
rendererMoveNode: 0,
|
||||
rendererRemoveNode: 0,
|
||||
rendererAppendChild: 0,
|
||||
rendererInsertBefore: 0,
|
||||
rendererCreateComment: 0,
|
||||
hydratedNodes: 0,
|
||||
hydratedComponents: 0,
|
||||
dehydratedViewsRemoved: 0,
|
||||
|
|
|
|||
|
|
@ -25,10 +25,6 @@ import {
|
|||
import {TestBed} from '@angular/core/testing';
|
||||
import {By} from '@angular/platform-browser';
|
||||
|
||||
function getNoOfNativeListeners(): number {
|
||||
return ngDevMode ? ngDevMode.rendererAddEventListener : 0;
|
||||
}
|
||||
|
||||
describe('event listeners', () => {
|
||||
describe('even handling statements', () => {
|
||||
it('should call function on event emit', () => {
|
||||
|
|
@ -371,17 +367,12 @@ describe('event listeners', () => {
|
|||
TestBed.configureTestingModule({
|
||||
declarations: [TestCmpt, WithClicksCmpt, LikesClicks, MdButton],
|
||||
});
|
||||
const noOfEventListenersRegisteredSoFar = getNoOfNativeListeners();
|
||||
|
||||
const fixture = TestBed.createComponent(TestCmpt);
|
||||
fixture.detectChanges();
|
||||
const buttonDebugEls = fixture.debugElement.queryAll(By.css('button'));
|
||||
const withClicksEls = fixture.debugElement.queryAll(By.css('with-clicks-cmpt'));
|
||||
|
||||
// We want to assert that only one native event handler was registered but still all
|
||||
// directives are notified when an event fires. This assertion can only be verified in
|
||||
// the ngDevMode (but the coalescing always happens!).
|
||||
ngDevMode && expect(getNoOfNativeListeners()).toBe(noOfEventListenersRegisteredSoFar + 2);
|
||||
|
||||
buttonDebugEls[0].nativeElement.click();
|
||||
expect(withClicksEls[0].injector.get(WithClicksCmpt).counter).toBe(1);
|
||||
expect(buttonDebugEls[0].injector.get(LikesClicks).counter).toBe(1);
|
||||
|
|
@ -412,16 +403,10 @@ describe('event listeners', () => {
|
|||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [TestCmpt, LikesClicks]});
|
||||
const noOfEventListenersRegisteredSoFar = getNoOfNativeListeners();
|
||||
const fixture = TestBed.createComponent(TestCmpt);
|
||||
fixture.detectChanges();
|
||||
const buttonDebugEl = fixture.debugElement.query(By.css('button'));
|
||||
|
||||
// We want to assert that only one native event handler was registered but still all
|
||||
// directives are notified when an event fires. This assertion can only be verified in
|
||||
// the ngDevMode (but the coalescing always happens!).
|
||||
ngDevMode && expect(getNoOfNativeListeners()).toBe(noOfEventListenersRegisteredSoFar + 1);
|
||||
|
||||
buttonDebugEl.nativeElement.click();
|
||||
expect(buttonDebugEl.injector.get(LikesClicks).counter).toBe(1);
|
||||
expect(fixture.componentInstance.counter).toBe(1);
|
||||
|
|
|
|||
|
|
@ -503,8 +503,6 @@ describe('Renderer2 destruction hooks', () => {
|
|||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.nativeElement.textContent).toBe('');
|
||||
expect(ngDevMode!.rendererDestroy).toBe(0);
|
||||
expect(ngDevMode!.rendererDestroyNode).toBe(3);
|
||||
});
|
||||
|
||||
it('should call renderer.destroy for each component destroyed', () => {
|
||||
|
|
@ -517,8 +515,6 @@ describe('Renderer2 destruction hooks', () => {
|
|||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.nativeElement.textContent).toBe('');
|
||||
expect(ngDevMode!.rendererDestroy).toBe(3);
|
||||
expect(ngDevMode!.rendererDestroyNode).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -923,11 +923,6 @@ describe('styling', () => {
|
|||
|
||||
const div = fixture.nativeElement.querySelector('div') as HTMLDivElement;
|
||||
expect(div.style.backgroundImage).toBe('url("#test")');
|
||||
|
||||
expectPerfCounters({
|
||||
rendererSetStyle: 1,
|
||||
tNode: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should set !important on a single property', () => {
|
||||
|
|
@ -948,11 +943,6 @@ describe('styling', () => {
|
|||
// We have to check the `style` attribute, because `element.style.prop` doesn't include
|
||||
// `!important`. Use a regex, because the different renderers produce different whitespace.
|
||||
expect(html).toMatch(/style=["|']width:\s*50px\s*!important/);
|
||||
|
||||
expectPerfCounters({
|
||||
rendererSetStyle: 1,
|
||||
tNode: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should set !important that is not preceded by a space', () => {
|
||||
|
|
@ -973,11 +963,6 @@ describe('styling', () => {
|
|||
// We have to check the `style` attribute, because `element.style.prop` doesn't include
|
||||
// `!important`. Use a regex, because the different renderers produce different whitespace.
|
||||
expect(html).toMatch(/style=["|']width:\s*50px\s*!important/);
|
||||
|
||||
expectPerfCounters({
|
||||
rendererSetStyle: 1,
|
||||
tNode: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should set !important on a dash-case property', () => {
|
||||
|
|
@ -998,11 +983,6 @@ describe('styling', () => {
|
|||
// We have to check the `style` attribute, because `element.style.prop` doesn't include
|
||||
// `!important`. Use a regex, because the different renderers produce different whitespace.
|
||||
expect(html).toMatch(/style=["|']margin-right:\s*5px\s*!important/);
|
||||
|
||||
expectPerfCounters({
|
||||
rendererSetStyle: 1,
|
||||
tNode: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should set !important on multiple properties', () => {
|
||||
|
|
@ -1023,11 +1003,6 @@ describe('styling', () => {
|
|||
// We have to check the `style` attribute, because `element.style.prop` doesn't include
|
||||
// `!important`. Use a regex, because the different renderers produce different whitespace.
|
||||
expect(html).toMatch(/style=["|']height:\s*25px\s*!important;\s*width:\s*50px\s*!important/);
|
||||
|
||||
expectPerfCounters({
|
||||
rendererSetStyle: 2,
|
||||
tNode: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should set !important if some properties are !important and other are not', () => {
|
||||
|
|
@ -1048,11 +1023,6 @@ describe('styling', () => {
|
|||
// We have to check the `style` attribute, because `element.style.prop` doesn't include
|
||||
// `!important`. Use a regex, because the different renderers produce different whitespace.
|
||||
expect(html).toMatch(/style=["|']height:\s*25px;\s*width:\s*50px\s*!important/);
|
||||
|
||||
expectPerfCounters({
|
||||
rendererSetStyle: 2,
|
||||
tNode: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not write to the native element if a directive shadows the class input', () => {
|
||||
|
|
@ -1948,7 +1918,6 @@ describe('styling', () => {
|
|||
expect(element.style.fontSize).toEqual('100px');
|
||||
|
||||
// once for the template flush and again for the host bindings
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(4);
|
||||
ngDevModeResetPerfCounters();
|
||||
|
||||
component.opacity = '0.6';
|
||||
|
|
@ -1961,9 +1930,6 @@ describe('styling', () => {
|
|||
expect(element.style.width).toEqual('100px');
|
||||
expect(element.style.height).toEqual('100px');
|
||||
expect(element.style.fontSize).toEqual('50px');
|
||||
|
||||
// once for the template flush and again for the host bindings
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(4);
|
||||
});
|
||||
|
||||
it('should combine all styling across the template, directive and component host bindings', () => {
|
||||
|
|
@ -2255,7 +2221,6 @@ describe('styling', () => {
|
|||
fixture.detectChanges();
|
||||
const element = fixture.nativeElement.querySelector('div');
|
||||
|
||||
assertStyleCounters(4, 0);
|
||||
assertStyle(element, 'width', '111px');
|
||||
assertStyle(element, 'height', '111px');
|
||||
|
||||
|
|
@ -2263,7 +2228,6 @@ describe('styling', () => {
|
|||
ngDevModeResetPerfCounters();
|
||||
fixture.detectChanges();
|
||||
|
||||
assertStyleCounters(1, 0);
|
||||
assertStyle(element, 'width', '222px');
|
||||
assertStyle(element, 'height', '111px');
|
||||
|
||||
|
|
@ -2271,7 +2235,6 @@ describe('styling', () => {
|
|||
ngDevModeResetPerfCounters();
|
||||
fixture.detectChanges();
|
||||
|
||||
assertStyleCounters(1, 0);
|
||||
assertStyle(element, 'width', '222px');
|
||||
assertStyle(element, 'height', '222px');
|
||||
|
||||
|
|
@ -2279,7 +2242,6 @@ describe('styling', () => {
|
|||
ngDevModeResetPerfCounters();
|
||||
fixture.detectChanges();
|
||||
|
||||
assertStyleCounters(1, 0);
|
||||
assertStyle(element, 'width', '555px');
|
||||
assertStyle(element, 'height', '222px');
|
||||
|
||||
|
|
@ -2296,7 +2258,6 @@ describe('styling', () => {
|
|||
fixture.detectChanges();
|
||||
|
||||
// No change, hence no write
|
||||
assertStyleCounters(0, 0);
|
||||
assertStyle(element, 'width', '123px');
|
||||
assertStyle(element, 'height', '123px');
|
||||
|
||||
|
|
@ -2304,7 +2265,6 @@ describe('styling', () => {
|
|||
ngDevModeResetPerfCounters();
|
||||
fixture.detectChanges();
|
||||
|
||||
assertStyleCounters(1, 0);
|
||||
assertStyle(element, 'width', '999px');
|
||||
assertStyle(element, 'height', '123px');
|
||||
|
||||
|
|
@ -2313,7 +2273,6 @@ describe('styling', () => {
|
|||
fixture.detectChanges();
|
||||
|
||||
// the width is only applied once
|
||||
assertStyleCounters(1, 0);
|
||||
assertStyle(element, 'width', '0px');
|
||||
assertStyle(element, 'height', '123px');
|
||||
|
||||
|
|
@ -2321,7 +2280,6 @@ describe('styling', () => {
|
|||
ngDevModeResetPerfCounters();
|
||||
fixture.detectChanges();
|
||||
|
||||
assertStyleCounters(2, 0);
|
||||
assertStyle(element, 'width', '1000px');
|
||||
assertStyle(element, 'height', '123px');
|
||||
assertStyle(element, 'color', 'red');
|
||||
|
|
@ -2332,7 +2290,6 @@ describe('styling', () => {
|
|||
|
||||
// height gets applied twice and all other
|
||||
// values get applied
|
||||
assertStyleCounters(1, 0);
|
||||
assertStyle(element, 'width', '1000px');
|
||||
assertStyle(element, 'height', '1100px');
|
||||
assertStyle(element, 'color', 'red');
|
||||
|
|
@ -2341,7 +2298,6 @@ describe('styling', () => {
|
|||
ngDevModeResetPerfCounters();
|
||||
fixture.detectChanges();
|
||||
|
||||
assertStyleCounters(3, 0);
|
||||
assertStyle(element, 'width', '2000px');
|
||||
assertStyle(element, 'height', '1100px');
|
||||
assertStyle(element, 'color', 'blue');
|
||||
|
|
@ -2352,7 +2308,6 @@ describe('styling', () => {
|
|||
fixture.detectChanges();
|
||||
|
||||
// all four are applied because the map was altered
|
||||
assertStyleCounters(0, 1);
|
||||
assertStyle(element, 'width', '2000px');
|
||||
assertStyle(element, 'height', '1100px');
|
||||
assertStyle(element, 'color', 'blue');
|
||||
|
|
@ -4144,11 +4099,6 @@ describe('styling', () => {
|
|||
});
|
||||
});
|
||||
|
||||
function assertStyleCounters(countForSet: number, countForRemove: number) {
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(countForSet);
|
||||
expect(ngDevMode!.rendererRemoveStyle).toEqual(countForRemove);
|
||||
}
|
||||
|
||||
function assertStyle(element: HTMLElement, prop: string, value: any) {
|
||||
expect((element.style as any)[prop]).toEqual(value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -913,7 +913,6 @@ describe('ViewContainerRef', () => {
|
|||
|
||||
expect(() => vcRefDir.vcref.detach(-1)).toThrow();
|
||||
expect(() => vcRefDir.vcref.detach(42)).toThrow();
|
||||
expect(ngDevMode!.rendererDestroyNode).toBe(0);
|
||||
});
|
||||
|
||||
it('should detach the last embedded view when no index is specified', () => {
|
||||
|
|
@ -935,7 +934,6 @@ describe('ViewContainerRef', () => {
|
|||
fixture.detectChanges();
|
||||
expect(getElementHtml(fixture.nativeElement)).toEqual('<p vcref=""></p>ABCD');
|
||||
expect(viewE.destroyed).toBeFalsy();
|
||||
expect(ngDevMode!.rendererDestroyNode).toBe(0);
|
||||
});
|
||||
|
||||
it('should not throw when destroying a detached component view', () => {
|
||||
|
|
@ -1013,7 +1011,6 @@ describe('ViewContainerRef', () => {
|
|||
|
||||
expect(() => vcRefDir.vcref.remove(-1)).toThrow();
|
||||
expect(() => vcRefDir.vcref.remove(42)).toThrow();
|
||||
expect(ngDevMode!.rendererDestroyNode).toBe(2);
|
||||
});
|
||||
|
||||
it('should remove the last embedded view when no index is specified', () => {
|
||||
|
|
@ -1035,7 +1032,6 @@ describe('ViewContainerRef', () => {
|
|||
fixture.detectChanges();
|
||||
expect(getElementHtml(fixture.nativeElement)).toEqual('<p vcref=""></p>ABCD');
|
||||
expect(viewE.destroyed).toBeTruthy();
|
||||
expect(ngDevMode!.rendererDestroyNode).toBe(1);
|
||||
});
|
||||
|
||||
it('should throw when trying to insert a removed or destroyed view', () => {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ import {HEADER_OFFSET, TVIEW} from '@angular/core/src/render3/interfaces/view';
|
|||
import {getLView, leaveView, setBindingRootForHostBindings} from '@angular/core/src/render3/state';
|
||||
import {getNativeByIndex} from '@angular/core/src/render3/util/view_utils';
|
||||
import {keyValueArraySet} from '@angular/core/src/util/array_utils';
|
||||
import {ngDevModeResetPerfCounters} from '@angular/core/src/util/ng_dev_mode';
|
||||
import {getElementClasses, getElementStyles} from '@angular/core/testing/src/styling';
|
||||
|
||||
import {clearFirstUpdatePass, enterViewWithOneDiv, rewindBindingIndex} from './shared_spec';
|
||||
|
|
@ -79,58 +78,40 @@ describe('styling', () => {
|
|||
});
|
||||
|
||||
it('should set style based on priority', () => {
|
||||
ngDevModeResetPerfCounters();
|
||||
ɵɵstyleProp('color', 'red');
|
||||
ɵɵstyleProp('color', 'blue'); // Higher priority, should win.
|
||||
expectStyle(div).toEqual({color: 'blue'});
|
||||
// The intermediate value has to set since it does not know if it is last one.
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(2);
|
||||
ngDevModeResetPerfCounters();
|
||||
|
||||
clearFirstUpdatePass();
|
||||
rewindBindingIndex();
|
||||
ɵɵstyleProp('color', 'red'); // no change
|
||||
ɵɵstyleProp('color', 'green'); // change to green
|
||||
expectStyle(div).toEqual({color: 'green'});
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(1);
|
||||
ngDevModeResetPerfCounters();
|
||||
|
||||
rewindBindingIndex();
|
||||
ɵɵstyleProp('color', 'black'); // First binding update
|
||||
expectStyle(div).toEqual({color: 'green'}); // Green still has priority.
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(0);
|
||||
ngDevModeResetPerfCounters();
|
||||
|
||||
rewindBindingIndex();
|
||||
ɵɵstyleProp('color', 'black'); // no change
|
||||
ɵɵstyleProp('color', undefined); // Clear second binding
|
||||
expectStyle(div).toEqual({color: 'black'}); // default to first binding
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(1);
|
||||
ngDevModeResetPerfCounters();
|
||||
|
||||
rewindBindingIndex();
|
||||
ɵɵstyleProp('color', null);
|
||||
expectStyle(div).toEqual({}); // default to first binding
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(0);
|
||||
expect(ngDevMode!.rendererRemoveStyle).toEqual(1);
|
||||
});
|
||||
|
||||
it('should set class based on priority', () => {
|
||||
ngDevModeResetPerfCounters();
|
||||
ɵɵclassProp('foo', false);
|
||||
ɵɵclassProp('foo', true); // Higher priority, should win.
|
||||
expectClass(div).toEqual({foo: true});
|
||||
expect(ngDevMode!.rendererAddClass).toEqual(1);
|
||||
ngDevModeResetPerfCounters();
|
||||
|
||||
clearFirstUpdatePass();
|
||||
rewindBindingIndex();
|
||||
ɵɵclassProp('foo', false); // no change
|
||||
ɵɵclassProp('foo', undefined); // change (have no opinion)
|
||||
expectClass(div).toEqual({});
|
||||
expect(ngDevMode!.rendererAddClass).toEqual(0);
|
||||
expect(ngDevMode!.rendererRemoveClass).toEqual(1);
|
||||
ngDevModeResetPerfCounters();
|
||||
|
||||
rewindBindingIndex();
|
||||
ɵɵclassProp('foo', false); // no change
|
||||
|
|
@ -145,67 +126,41 @@ describe('styling', () => {
|
|||
|
||||
describe('styleMap', () => {
|
||||
it('should work with maps', () => {
|
||||
ngDevModeResetPerfCounters();
|
||||
ɵɵstyleMap({});
|
||||
expectStyle(div).toEqual({});
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(0);
|
||||
expect(ngDevMode!.rendererRemoveStyle).toEqual(0);
|
||||
ngDevModeResetPerfCounters();
|
||||
|
||||
clearFirstUpdatePass();
|
||||
|
||||
rewindBindingIndex();
|
||||
ɵɵstyleMap({color: 'blue'});
|
||||
expectStyle(div).toEqual({color: 'blue'});
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(1);
|
||||
expect(ngDevMode!.rendererRemoveStyle).toEqual(0);
|
||||
ngDevModeResetPerfCounters();
|
||||
|
||||
rewindBindingIndex();
|
||||
ɵɵstyleMap({color: 'red'});
|
||||
expectStyle(div).toEqual({color: 'red'});
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(1);
|
||||
expect(ngDevMode!.rendererRemoveStyle).toEqual(0);
|
||||
ngDevModeResetPerfCounters();
|
||||
|
||||
rewindBindingIndex();
|
||||
ɵɵstyleMap({color: null, width: '100px'});
|
||||
expectStyle(div).toEqual({width: '100px'});
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(1);
|
||||
expect(ngDevMode!.rendererRemoveStyle).toEqual(1);
|
||||
ngDevModeResetPerfCounters();
|
||||
});
|
||||
|
||||
it('should work with object literal and strings', () => {
|
||||
ngDevModeResetPerfCounters();
|
||||
ɵɵstyleMap('');
|
||||
expectStyle(div).toEqual({});
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(0);
|
||||
expect(ngDevMode!.rendererRemoveStyle).toEqual(0);
|
||||
ngDevModeResetPerfCounters();
|
||||
|
||||
clearFirstUpdatePass();
|
||||
|
||||
rewindBindingIndex();
|
||||
ɵɵstyleMap('color: blue');
|
||||
expectStyle(div).toEqual({color: 'blue'});
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(1);
|
||||
expect(ngDevMode!.rendererRemoveStyle).toEqual(0);
|
||||
ngDevModeResetPerfCounters();
|
||||
|
||||
rewindBindingIndex();
|
||||
ɵɵstyleMap('color: red');
|
||||
expectStyle(div).toEqual({color: 'red'});
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(1);
|
||||
expect(ngDevMode!.rendererRemoveStyle).toEqual(0);
|
||||
ngDevModeResetPerfCounters();
|
||||
|
||||
rewindBindingIndex();
|
||||
ɵɵstyleMap('width: 100px');
|
||||
expectStyle(div).toEqual({width: '100px'});
|
||||
expect(ngDevMode!.rendererSetStyle).toEqual(1);
|
||||
expect(ngDevMode!.rendererRemoveStyle).toEqual(1);
|
||||
ngDevModeResetPerfCounters();
|
||||
});
|
||||
|
||||
it('should collaborate with properties', () => {
|
||||
|
|
|
|||
|
|
@ -6,10 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {Component, Input} from '@angular/core/public_api';
|
||||
import {ngDevModeResetPerfCounters} from '@angular/core/src/util/ng_dev_mode';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {getSortedClassName} from '@angular/core/testing/src/styling';
|
||||
|
||||
import {
|
||||
|
|
@ -77,8 +74,7 @@ describe('instructions', () => {
|
|||
});
|
||||
|
||||
describe('bind', () => {
|
||||
it('should update bindings when value changes with the correct perf counters', () => {
|
||||
ngDevModeResetPerfCounters();
|
||||
it('should update bindings when value changes', () => {
|
||||
const t = new ViewFixture({create: createAnchor, decls: 1, vars: 1});
|
||||
|
||||
t.update(() => {
|
||||
|
|
@ -90,19 +86,9 @@ describe('instructions', () => {
|
|||
ɵɵproperty('title', 'World');
|
||||
});
|
||||
expect(t.html).toEqual('<a title="World"></a>');
|
||||
expect(ngDevMode).toEqual(
|
||||
jasmine.objectContaining({
|
||||
firstCreatePass: 1,
|
||||
tNode: 2, // 1 for hostElement + 1 for the template under test
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 2,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should not update bindings when value does not change, with the correct perf counters', () => {
|
||||
ngDevModeResetPerfCounters();
|
||||
const idempotentUpdate = () => {
|
||||
ɵɵproperty('title', 'Hello');
|
||||
};
|
||||
|
|
@ -118,21 +104,11 @@ describe('instructions', () => {
|
|||
|
||||
t.update();
|
||||
expect(t.html).toEqual('<a title="Hello"></a>');
|
||||
expect(ngDevMode).toEqual(
|
||||
jasmine.objectContaining({
|
||||
firstCreatePass: 1,
|
||||
tNode: 2, // 1 for hostElement + 1 for the template under test
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 1,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('element', () => {
|
||||
it('should create an element with the correct perf counters', () => {
|
||||
ngDevModeResetPerfCounters();
|
||||
it('should create an element', () => {
|
||||
const t = new ViewFixture({
|
||||
create: () => {
|
||||
ɵɵelement(0, 'div', 0);
|
||||
|
|
@ -145,14 +121,6 @@ describe('instructions', () => {
|
|||
const div = (t.host as HTMLElement).querySelector('div')!;
|
||||
expect(div.id).toEqual('test');
|
||||
expect(div.title).toEqual('Hello');
|
||||
expect(ngDevMode).toEqual(
|
||||
jasmine.objectContaining({
|
||||
firstCreatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should instantiate nodes at high indices', () => {
|
||||
|
|
@ -193,7 +161,6 @@ describe('instructions', () => {
|
|||
|
||||
describe('attribute', () => {
|
||||
it('should use sanitizer function', () => {
|
||||
ngDevModeResetPerfCounters();
|
||||
const t = new ViewFixture({create: createDiv, decls: 1, vars: 1});
|
||||
|
||||
t.update(() => {
|
||||
|
|
@ -205,15 +172,6 @@ describe('instructions', () => {
|
|||
ɵɵattribute('title', bypassSanitizationTrustUrl('javascript:true'), ɵɵsanitizeUrl);
|
||||
});
|
||||
expect(t.html).toEqual('<div title="javascript:true"></div>');
|
||||
expect(ngDevMode).toEqual(
|
||||
jasmine.objectContaining({
|
||||
firstCreatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetAttribute: 2,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -224,7 +182,6 @@ describe('instructions', () => {
|
|||
* is not producing chained instructions yet.
|
||||
*/
|
||||
it('should chain', () => {
|
||||
ngDevModeResetPerfCounters();
|
||||
// <div [title]="title" [accesskey]="key"></div>
|
||||
const t = new ViewFixture({create: createDiv, update: () => {}, decls: 1, vars: 2});
|
||||
t.update(() => {
|
||||
|
|
@ -235,15 +192,6 @@ describe('instructions', () => {
|
|||
ɵɵproperty('title', 'two')('accessKey', 'B');
|
||||
});
|
||||
expect(t.html).toEqual('<div accesskey="B" title="two"></div>');
|
||||
expect(ngDevMode).toEqual(
|
||||
jasmine.objectContaining({
|
||||
firstCreatePass: 1,
|
||||
tNode: 2, // 1 for div, 1 for host element
|
||||
tView: 2, // 1 for rootView + 1 for the template view
|
||||
rendererCreateElement: 1,
|
||||
rendererSetProperty: 4,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -318,36 +266,6 @@ describe('instructions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('performance counters', () => {
|
||||
it('should create tView only once for each nested level', () => {
|
||||
@Component({
|
||||
selector: 'nested-loops',
|
||||
template: `
|
||||
<ul *ngFor="let row of rows">
|
||||
<li *ngFor="let col of row.cols">{{col}}</li>
|
||||
</ul>
|
||||
`,
|
||||
imports: [CommonModule],
|
||||
})
|
||||
class NestedLoops {
|
||||
rows = [
|
||||
['a', 'b'],
|
||||
['A', 'B'],
|
||||
['a', 'b'],
|
||||
['A', 'B'],
|
||||
];
|
||||
}
|
||||
ngDevModeResetPerfCounters();
|
||||
TestBed.createComponent(NestedLoops);
|
||||
expect(ngDevMode).toEqual(
|
||||
jasmine.objectContaining({
|
||||
// Expect: component view + ngFor(row) + ngFor(col)
|
||||
tView: 3, // should be: 3
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sanitization injection compatibility', () => {
|
||||
it('should work for url sanitization', () => {
|
||||
const s = new LocalMockSanitizer((value) => `${value}-sanitized`);
|
||||
|
|
|
|||
Loading…
Reference in a new issue