From b016497618e0264a4059f4ebf7fa01493d3bcec9 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Thu, 5 Sep 2019 21:44:08 +0200 Subject: [PATCH] feat(core): allow more granular control over sanity checks Allows consumers to disable individual sanity checks, rather than the all-or-nothing setup that we have at the moment. Fixes #16617. --- .../core/common-behaviors/common-module.ts | 56 +++++++++++++++---- src/material/core/common-behaviors/index.ts | 7 ++- tools/public_api_guard/material/core.d.ts | 13 ++++- 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/src/material/core/common-behaviors/common-module.ts b/src/material/core/common-behaviors/common-module.ts index ff38e7f0a5b1..cff7906b5d88 100644 --- a/src/material/core/common-behaviors/common-module.ts +++ b/src/material/core/common-behaviors/common-module.ts @@ -18,16 +18,30 @@ import {VERSION as CDK_VERSION} from '@angular/cdk'; const VERSION = new Version('0.0.0-PLACEHOLDER'); /** @docs-private */ -export function MATERIAL_SANITY_CHECKS_FACTORY(): boolean { +export function MATERIAL_SANITY_CHECKS_FACTORY(): SanityChecks { return true; } /** Injection token that configures whether the Material sanity checks are enabled. */ -export const MATERIAL_SANITY_CHECKS = new InjectionToken('mat-sanity-checks', { +export const MATERIAL_SANITY_CHECKS = new InjectionToken('mat-sanity-checks', { providedIn: 'root', factory: MATERIAL_SANITY_CHECKS_FACTORY, }); +/** + * Possible sanity checks that can be enabled. If set to + * true/false, all checks will be enabled/disabled. + */ +export type SanityChecks = boolean | GranularSanityChecks; + +/** Object that can be used to configure the sanity checks granularly. */ +export interface GranularSanityChecks { + doctype: boolean; + theme: boolean; + version: boolean; + hammer: boolean; +} + /** * Module that captures anything that should be loaded and/or run for *all* Angular Material * components. This includes Bidi, etc. @@ -51,11 +65,18 @@ export class MatCommonModule { /** Reference to the global 'window' object. */ private _window = typeof window === 'object' && window ? window : null; + /** Configured sanity checks. */ + private _sanityChecks: SanityChecks; + constructor( - @Optional() @Inject(MATERIAL_SANITY_CHECKS) private _sanityChecksEnabled: boolean, + @Optional() @Inject(MATERIAL_SANITY_CHECKS) sanityChecks: any, @Optional() @Inject(HAMMER_LOADER) private _hammerLoader?: HammerLoader) { - if (this._areChecksEnabled() && !this._hasDoneGlobalChecks) { + // Note that `_sanityChecks` is typed to `any`, because AoT + // throws an error if we use the `SanityChecks` type directly. + this._sanityChecks = sanityChecks; + + if (!this._hasDoneGlobalChecks) { this._checkDoctypeIsDefined(); this._checkThemeIsPresent(); this._checkCdkVersionMatch(); @@ -63,9 +84,9 @@ export class MatCommonModule { } } - /** Whether any sanity checks are enabled */ - private _areChecksEnabled(): boolean { - return this._sanityChecksEnabled && isDevMode() && !this._isTestEnv(); + /** Whether any sanity checks are enabled. */ + private _checksAreEnabled(): boolean { + return isDevMode() && !this._isTestEnv(); } /** Whether the code is running in tests. */ @@ -75,7 +96,10 @@ export class MatCommonModule { } private _checkDoctypeIsDefined(): void { - if (this._document && !this._document.doctype) { + const isEnabled = this._checksAreEnabled() && + (this._sanityChecks === true || (this._sanityChecks as GranularSanityChecks).doctype); + + if (isEnabled && this._document && !this._document.doctype) { console.warn( 'Current document does not have a doctype. This may cause ' + 'some Angular Material components not to behave as expected.' @@ -86,7 +110,11 @@ export class MatCommonModule { private _checkThemeIsPresent(): void { // We need to assert that the `body` is defined, because these checks run very early // and the `body` won't be defined if the consumer put their scripts in the `head`. - if (!this._document || !this._document.body || typeof getComputedStyle !== 'function') { + const isDisabled = !this._checksAreEnabled() || + (this._sanityChecks === false || !(this._sanityChecks as GranularSanityChecks).theme); + + if (isDisabled || !this._document || !this._document.body || + typeof getComputedStyle !== 'function') { return; } @@ -113,7 +141,10 @@ export class MatCommonModule { /** Checks whether the material version matches the cdk version */ private _checkCdkVersionMatch(): void { - if (VERSION.full !== CDK_VERSION.full) { + const isEnabled = this._checksAreEnabled() && + (this._sanityChecks === true || (this._sanityChecks as GranularSanityChecks).version); + + if (isEnabled && VERSION.full !== CDK_VERSION.full) { console.warn( 'The Angular Material version (' + VERSION.full + ') does not match ' + 'the Angular CDK version (' + CDK_VERSION.full + ').\n' + @@ -128,7 +159,10 @@ export class MatCommonModule { return; } - if (this._areChecksEnabled() && !(this._window as any)['Hammer'] && !this._hammerLoader) { + const isEnabled = this._checksAreEnabled() && + (this._sanityChecks === true || (this._sanityChecks as GranularSanityChecks).hammer); + + if (isEnabled && !(this._window as any)['Hammer'] && !this._hammerLoader) { console.warn( 'Could not find HammerJS. Certain Angular Material components may not work correctly.'); } diff --git a/src/material/core/common-behaviors/index.ts b/src/material/core/common-behaviors/index.ts index e6e014408be0..8d29f9be5a26 100644 --- a/src/material/core/common-behaviors/index.ts +++ b/src/material/core/common-behaviors/index.ts @@ -6,7 +6,12 @@ * found in the LICENSE file at https://angular.io/license */ -export {MatCommonModule, MATERIAL_SANITY_CHECKS} from './common-module'; +export { + MatCommonModule, + MATERIAL_SANITY_CHECKS, + SanityChecks, + GranularSanityChecks, +} from './common-module'; export {CanDisable, CanDisableCtor, mixinDisabled} from './disabled'; export {CanColor, CanColorCtor, mixinColor, ThemePalette} from './color'; export {CanDisableRipple, CanDisableRippleCtor, mixinDisableRipple} from './disable-ripple'; diff --git a/tools/public_api_guard/material/core.d.ts b/tools/public_api_guard/material/core.d.ts index 4b049bb9cfdc..631cb5bfab34 100644 --- a/tools/public_api_guard/material/core.d.ts +++ b/tools/public_api_guard/material/core.d.ts @@ -100,6 +100,13 @@ export declare class GestureConfig extends HammerGestureConfig { buildHammer(element: HTMLElement): HammerInstance; } +export interface GranularSanityChecks { + doctype: boolean; + hammer: boolean; + theme: boolean; + version: boolean; +} + export interface HammerInput { center: { x: number; @@ -190,7 +197,7 @@ export declare const MAT_OPTION_PARENT_COMPONENT: InjectionToken; export declare class MatCommonModule { - constructor(_sanityChecksEnabled: boolean, _hammerLoader?: HammerLoader | undefined); + constructor(sanityChecks: any, _hammerLoader?: HammerLoader | undefined); _checkHammerIsAvailable(): void; } @@ -206,7 +213,7 @@ export declare type MatDateFormats = { }; }; -export declare const MATERIAL_SANITY_CHECKS: InjectionToken; +export declare const MATERIAL_SANITY_CHECKS: InjectionToken; export declare class MatLine { } @@ -412,6 +419,8 @@ export interface RippleTarget { rippleDisabled: boolean; } +export declare type SanityChecks = boolean | GranularSanityChecks; + export declare const JAN = 0, FEB = 1, MAR = 2, APR = 3, MAY = 4, JUN = 5, JUL = 6, AUG = 7, SEP = 8, OCT = 9, NOV = 10, DEC = 11; export declare function setLines(lines: QueryList, element: ElementRef): void;