refactor(ivy): ensure `StylingDebug` instances provide context debug info (#32856)
This patch enables a styling debug instance (which is apart of the `debugNode.styles` or `debugNode.classes` data structures) to expose its context value so that it can be easily debugged. PR Close #32856
This commit is contained in:
parent
728cd8446f
commit
35a95a8a7e
|
@ -20,7 +20,7 @@ import {TQueries} from '../interfaces/query';
|
|||
import {RComment, RElement, RNode} from '../interfaces/renderer';
|
||||
import {TStylingContext} from '../interfaces/styling';
|
||||
import {BINDING_INDEX, CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_VIEW, ExpandoInstructions, FLAGS, HEADER_OFFSET, HOST, HookData, INJECTOR, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, RENDERER_FACTORY, SANITIZER, TData, TVIEW, TView as ITView, TView, T_HOST} from '../interfaces/view';
|
||||
import {DebugStyling as DebugNewStyling, NodeStylingDebug} from '../styling/styling_debug';
|
||||
import {DebugNodeStyling, NodeStylingDebug} from '../styling/styling_debug';
|
||||
import {attachDebugObject} from '../util/debug_utils';
|
||||
import {isStylingContext} from '../util/styling_utils';
|
||||
import {getTNode, unwrapRNode} from '../util/view_utils';
|
||||
|
@ -343,8 +343,8 @@ export class LViewDebug {
|
|||
export interface DebugNode {
|
||||
html: string|null;
|
||||
native: Node;
|
||||
styles: DebugNewStyling|null;
|
||||
classes: DebugNewStyling|null;
|
||||
styles: DebugNodeStyling|null;
|
||||
classes: DebugNodeStyling|null;
|
||||
nodes: DebugNode[]|null;
|
||||
component: LViewDebug|null;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import {RElement} from '../interfaces/renderer';
|
|||
import {ApplyStylingFn, LStylingData, TStylingConfig, TStylingContext, TStylingContextIndex} from '../interfaces/styling';
|
||||
import {getCurrentStyleSanitizer} from '../state';
|
||||
import {attachDebugObject} from '../util/debug_utils';
|
||||
import {allowDirectStyling as _allowDirectStyling, getDefaultValue, getGuardMask, getProp, getPropValuesStartPosition, getValuesCount, hasConfig, isContextLocked, isSanitizationRequired} from '../util/styling_utils';
|
||||
import {allowDirectStyling as _allowDirectStyling, getDefaultValue, getGuardMask, getProp, getPropValuesStartPosition, getValuesCount, hasConfig, isContextLocked, isSanitizationRequired, isStylingContext} from '../util/styling_utils';
|
||||
|
||||
import {applyStylingViaContext} from './bindings';
|
||||
import {activateStylingMapFeature} from './map_based_bindings';
|
||||
|
@ -27,65 +27,42 @@ import {activateStylingMapFeature} from './map_based_bindings';
|
|||
* --------
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* A debug/testing-oriented summary of a styling entry.
|
||||
* A debug-friendly version of `TStylingContext`.
|
||||
*
|
||||
* A value such as this is generated as an artifact of the `DebugStyling`
|
||||
* summary.
|
||||
* An instance of this is attached to `tStylingContext.debug` when `ngDevMode` is active.
|
||||
*/
|
||||
export interface LStylingSummary {
|
||||
/** The style/class property that the summary is attached to */
|
||||
prop: string;
|
||||
export interface DebugStylingContext {
|
||||
/** The configuration settings of the associated `TStylingContext` */
|
||||
config: DebugStylingConfig;
|
||||
|
||||
/** The last applied value for the style/class property */
|
||||
value: string|boolean|null;
|
||||
|
||||
/** The binding index of the last applied style/class property */
|
||||
bindingIndex: number|null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A debug/testing-oriented summary of all styling entries for a `DebugNode` instance.
|
||||
*/
|
||||
export interface DebugStyling {
|
||||
/** The associated TStylingContext instance */
|
||||
context: TStylingContext;
|
||||
|
||||
/** Which configuration flags are active (see `TStylingContextConfig`) */
|
||||
config: {
|
||||
hasMapBindings: boolean; //
|
||||
hasPropBindings: boolean; //
|
||||
hasCollisions: boolean; //
|
||||
hasTemplateBindings: boolean; //
|
||||
hasHostBindings: boolean; //
|
||||
templateBindingsLocked: boolean; //
|
||||
hostBindingsLocked: boolean; //
|
||||
allowDirectStyling: boolean; //
|
||||
};
|
||||
|
||||
/**
|
||||
* A summarization of each style/class property
|
||||
* present in the context
|
||||
*/
|
||||
summary: {[propertyName: string]: LStylingSummary};
|
||||
|
||||
/**
|
||||
* A key/value map of all styling properties and their
|
||||
* runtime values
|
||||
*/
|
||||
values: {[propertyName: string]: string | number | null | boolean};
|
||||
|
||||
/**
|
||||
* Overrides the sanitizer used to process styles
|
||||
*/
|
||||
overrideSanitizer(sanitizer: StyleSanitizeFn|null): void;
|
||||
/** The associated TStylingContext instance */
|
||||
entries: {[prop: string]: DebugStylingContextEntry};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A debug/testing-oriented summary of `TStylingConfig`.
|
||||
*/
|
||||
export interface DebugStylingConfig {
|
||||
hasMapBindings: boolean; //
|
||||
hasPropBindings: boolean; //
|
||||
hasCollisions: boolean; //
|
||||
hasTemplateBindings: boolean; //
|
||||
hasHostBindings: boolean; //
|
||||
templateBindingsLocked: boolean; //
|
||||
hostBindingsLocked: boolean; //
|
||||
allowDirectStyling: boolean; //
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A debug/testing-oriented summary of all styling entries within a `TStylingContext`.
|
||||
*/
|
||||
export interface TStylingTupleSummary {
|
||||
export interface DebugStylingContextEntry {
|
||||
/** The property (style or class property) that this tuple represents */
|
||||
prop: string;
|
||||
|
||||
|
@ -120,6 +97,51 @@ export interface TStylingTupleSummary {
|
|||
sources: (number|null|string)[];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A debug/testing-oriented summary of all styling entries for a `DebugNode` instance.
|
||||
*/
|
||||
export interface DebugNodeStyling {
|
||||
/** The associated debug context of the TStylingContext instance */
|
||||
context: DebugStylingContext;
|
||||
|
||||
/**
|
||||
* A summarization of each style/class property
|
||||
* present in the context
|
||||
*/
|
||||
summary: {[propertyName: string]: DebugNodeStylingEntry};
|
||||
|
||||
/**
|
||||
* A key/value map of all styling properties and their
|
||||
* runtime values
|
||||
*/
|
||||
values: {[propertyName: string]: string | number | null | boolean};
|
||||
|
||||
/**
|
||||
* Overrides the sanitizer used to process styles
|
||||
*/
|
||||
overrideSanitizer(sanitizer: StyleSanitizeFn|null): void;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A debug/testing-oriented summary of a styling entry.
|
||||
*
|
||||
* A value such as this is generated as an artifact of the `DebugStyling`
|
||||
* summary.
|
||||
*/
|
||||
export interface DebugNodeStylingEntry {
|
||||
/** The style/class property that the summary is attached to */
|
||||
prop: string;
|
||||
|
||||
/** The last applied value for the style/class property */
|
||||
value: string|boolean|null;
|
||||
|
||||
/** The binding index of the last applied style/class property */
|
||||
bindingIndex: number|null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates and attaches an instance of `TStylingContextDebug` to the provided context
|
||||
*/
|
||||
|
@ -135,21 +157,20 @@ export function attachStylingDebugObject(context: TStylingContext) {
|
|||
* This class is designed to be used within testing code or when an
|
||||
* application has `ngDevMode` activated.
|
||||
*/
|
||||
class TStylingContextDebug {
|
||||
class TStylingContextDebug implements DebugStylingContext {
|
||||
constructor(public readonly context: TStylingContext) {}
|
||||
|
||||
get isTemplateLocked() { return isContextLocked(this.context, true); }
|
||||
get isHostBindingsLocked() { return isContextLocked(this.context, false); }
|
||||
get config(): DebugStylingConfig { return buildConfig(this.context); }
|
||||
|
||||
/**
|
||||
* Returns a detailed summary of each styling entry in the context.
|
||||
*
|
||||
* See `TStylingTupleSummary`.
|
||||
*/
|
||||
get entries(): {[prop: string]: TStylingTupleSummary} {
|
||||
get entries(): {[prop: string]: DebugStylingContextEntry} {
|
||||
const context = this.context;
|
||||
const totalColumns = getValuesCount(context);
|
||||
const entries: {[prop: string]: TStylingTupleSummary} = {};
|
||||
const entries: {[prop: string]: DebugStylingContextEntry} = {};
|
||||
const start = getPropValuesStartPosition(context);
|
||||
let i = start;
|
||||
while (i < context.length) {
|
||||
|
@ -189,12 +210,19 @@ class TStylingContextDebug {
|
|||
* This class is designed to be used within testing code or when an
|
||||
* application has `ngDevMode` activated.
|
||||
*/
|
||||
export class NodeStylingDebug implements DebugStyling {
|
||||
export class NodeStylingDebug implements DebugNodeStyling {
|
||||
private _sanitizer: StyleSanitizeFn|null = null;
|
||||
private _debugContext: DebugStylingContext;
|
||||
|
||||
constructor(
|
||||
public context: TStylingContext, private _data: LStylingData,
|
||||
private _isClassBased?: boolean) {}
|
||||
context: TStylingContext|DebugStylingContext, private _data: LStylingData,
|
||||
private _isClassBased?: boolean) {
|
||||
this._debugContext = isStylingContext(context) ?
|
||||
new TStylingContextDebug(context as TStylingContext) :
|
||||
(context as DebugStylingContext);
|
||||
}
|
||||
|
||||
get context() { return this._debugContext; }
|
||||
|
||||
/**
|
||||
* Overrides the sanitizer used to process styles.
|
||||
|
@ -207,36 +235,15 @@ export class NodeStylingDebug implements DebugStyling {
|
|||
*
|
||||
* See `LStylingSummary`.
|
||||
*/
|
||||
get summary(): {[key: string]: LStylingSummary} {
|
||||
const entries: {[key: string]: LStylingSummary} = {};
|
||||
get summary(): {[key: string]: DebugNodeStylingEntry} {
|
||||
const entries: {[key: string]: DebugNodeStylingEntry} = {};
|
||||
this._mapValues((prop: string, value: any, bindingIndex: number | null) => {
|
||||
entries[prop] = {prop, value, bindingIndex};
|
||||
});
|
||||
return entries;
|
||||
}
|
||||
|
||||
get config() {
|
||||
const hasMapBindings = hasConfig(this.context, TStylingConfig.HasMapBindings);
|
||||
const hasPropBindings = hasConfig(this.context, TStylingConfig.HasPropBindings);
|
||||
const hasCollisions = hasConfig(this.context, TStylingConfig.HasCollisions);
|
||||
const hasTemplateBindings = hasConfig(this.context, TStylingConfig.HasTemplateBindings);
|
||||
const hasHostBindings = hasConfig(this.context, TStylingConfig.HasHostBindings);
|
||||
const templateBindingsLocked = hasConfig(this.context, TStylingConfig.TemplateBindingsLocked);
|
||||
const hostBindingsLocked = hasConfig(this.context, TStylingConfig.HostBindingsLocked);
|
||||
const allowDirectStyling =
|
||||
_allowDirectStyling(this.context, false) || _allowDirectStyling(this.context, true);
|
||||
|
||||
return {
|
||||
hasMapBindings, //
|
||||
hasPropBindings, //
|
||||
hasCollisions, //
|
||||
hasTemplateBindings, //
|
||||
hasHostBindings, //
|
||||
templateBindingsLocked, //
|
||||
hostBindingsLocked, //
|
||||
allowDirectStyling, //
|
||||
};
|
||||
}
|
||||
get config() { return buildConfig(this.context.context); }
|
||||
|
||||
/**
|
||||
* Returns a key/value map of all the styles/classes that were last applied to the element.
|
||||
|
@ -252,7 +259,7 @@ export class NodeStylingDebug implements DebugStyling {
|
|||
// element is only used when the styling algorithm attempts to
|
||||
// style the value (and we mock out the stylingApplyFn anyway).
|
||||
const mockElement = {} as any;
|
||||
const hasMaps = hasConfig(this.context, TStylingConfig.HasMapBindings);
|
||||
const hasMaps = hasConfig(this.context.context, TStylingConfig.HasMapBindings);
|
||||
if (hasMaps) {
|
||||
activateStylingMapFeature();
|
||||
}
|
||||
|
@ -265,10 +272,33 @@ export class NodeStylingDebug implements DebugStyling {
|
|||
|
||||
// run the template bindings
|
||||
applyStylingViaContext(
|
||||
this.context, null, mockElement, this._data, true, mapFn, sanitizer, false);
|
||||
this.context.context, null, mockElement, this._data, true, mapFn, sanitizer, false);
|
||||
|
||||
// and also the host bindings
|
||||
applyStylingViaContext(
|
||||
this.context, null, mockElement, this._data, true, mapFn, sanitizer, true);
|
||||
this.context.context, null, mockElement, this._data, true, mapFn, sanitizer, true);
|
||||
}
|
||||
}
|
||||
|
||||
function buildConfig(context: TStylingContext) {
|
||||
const hasMapBindings = hasConfig(context, TStylingConfig.HasMapBindings);
|
||||
const hasPropBindings = hasConfig(context, TStylingConfig.HasPropBindings);
|
||||
const hasCollisions = hasConfig(context, TStylingConfig.HasCollisions);
|
||||
const hasTemplateBindings = hasConfig(context, TStylingConfig.HasTemplateBindings);
|
||||
const hasHostBindings = hasConfig(context, TStylingConfig.HasHostBindings);
|
||||
const templateBindingsLocked = hasConfig(context, TStylingConfig.TemplateBindingsLocked);
|
||||
const hostBindingsLocked = hasConfig(context, TStylingConfig.HostBindingsLocked);
|
||||
const allowDirectStyling =
|
||||
_allowDirectStyling(context, false) || _allowDirectStyling(context, true);
|
||||
|
||||
return {
|
||||
hasMapBindings, //
|
||||
hasPropBindings, //
|
||||
hasCollisions, //
|
||||
hasTemplateBindings, //
|
||||
hasHostBindings, //
|
||||
templateBindingsLocked, //
|
||||
hostBindingsLocked, //
|
||||
allowDirectStyling, //
|
||||
};
|
||||
}
|
||||
|
|
|
@ -240,7 +240,7 @@ export function getStylingMapArray(value: TStylingContext | StylingMapArray | nu
|
|||
value as StylingMapArray;
|
||||
}
|
||||
|
||||
export function isStylingContext(value: TStylingContext | StylingMapArray | null): boolean {
|
||||
export function isStylingContext(value: any): boolean {
|
||||
// the StylingMapArray is in the format of [initial, prop, string, prop, string]
|
||||
// and this is the defining value to distinguish between arrays
|
||||
return Array.isArray(value) && value.length >= TStylingContextIndex.ValuesStartPosition &&
|
||||
|
|
|
@ -863,7 +863,7 @@ describe('styling', () => {
|
|||
const node = getDebugNode(element) !;
|
||||
|
||||
const styles = node.styles !;
|
||||
const config = styles.config;
|
||||
const config = styles.context.config;
|
||||
expect(config.hasCollisions).toBeFalsy();
|
||||
expect(config.hasMapBindings).toBeFalsy();
|
||||
expect(config.hasPropBindings).toBeTruthy();
|
||||
|
|
Loading…
Reference in New Issue