Skip to content

Commit

Permalink
feat(core): allow more granular control over sanity checks
Browse files Browse the repository at this point in the history
Allows consumers to disable individual sanity checks, rather than the all-or-nothing setup that we have at the moment.

Fixes angular#16617.
  • Loading branch information
crisbeto committed Sep 4, 2019
1 parent 1c74518 commit 47ade95
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 14 deletions.
53 changes: 42 additions & 11 deletions src/material/core/common-behaviors/common-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,27 @@ 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<boolean>('mat-sanity-checks', {
export const MATERIAL_SANITY_CHECKS = new InjectionToken<SanityChecks>('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 | {
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.
Expand All @@ -51,21 +62,28 @@ 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();
this._hasDoneGlobalChecks = true;
}
}

/** 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. */
Expand All @@ -75,7 +93,10 @@ export class MatCommonModule {
}

private _checkDoctypeIsDefined(): void {
if (this._document && !this._document.doctype) {
const isEnabled = this._checksAreEnabled() &&
(typeof this._sanityChecks === 'boolean' ? this._sanityChecks : this._sanityChecks.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.'
Expand All @@ -86,7 +107,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() ||
(typeof this._sanityChecks === 'boolean' ? !this._sanityChecks : !this._sanityChecks.theme);

if (isDisabled || !this._document || !this._document.body ||
typeof getComputedStyle !== 'function') {
return;
}

Expand All @@ -113,7 +138,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() &&
(typeof this._sanityChecks === 'boolean' ? this._sanityChecks : this._sanityChecks.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' +
Expand All @@ -128,7 +156,10 @@ export class MatCommonModule {
return;
}

if (this._areChecksEnabled() && !(this._window as any)['Hammer'] && !this._hammerLoader) {
const isEnabled = this._checksAreEnabled() &&
(typeof this._sanityChecks === 'boolean' ? this._sanityChecks : this._sanityChecks.hammer);

if (isEnabled && !(this._window as any)['Hammer'] && !this._hammerLoader) {
console.warn(
'Could not find HammerJS. Certain Angular Material components may not work correctly.');
}
Expand Down
2 changes: 1 addition & 1 deletion src/material/core/common-behaviors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

export {MatCommonModule, MATERIAL_SANITY_CHECKS} from './common-module';
export {MatCommonModule, MATERIAL_SANITY_CHECKS, SanityChecks} from './common-module';
export {CanDisable, CanDisableCtor, mixinDisabled} from './disabled';
export {CanColor, CanColorCtor, mixinColor, ThemePalette} from './color';
export {CanDisableRipple, CanDisableRippleCtor, mixinDisableRipple} from './disable-ripple';
Expand Down
11 changes: 9 additions & 2 deletions tools/public_api_guard/material/core.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ export declare const MAT_OPTION_PARENT_COMPONENT: InjectionToken<MatOptionParent
export declare const MAT_RIPPLE_GLOBAL_OPTIONS: InjectionToken<RippleGlobalOptions>;

export declare class MatCommonModule {
constructor(_sanityChecksEnabled: boolean, _hammerLoader?: HammerLoader | undefined);
constructor(sanityChecks: any, _hammerLoader?: HammerLoader | undefined);
_checkHammerIsAvailable(): void;
}

Expand All @@ -206,7 +206,7 @@ export declare type MatDateFormats = {
};
};

export declare const MATERIAL_SANITY_CHECKS: InjectionToken<boolean>;
export declare const MATERIAL_SANITY_CHECKS: InjectionToken<SanityChecks>;

export declare class MatLine {
}
Expand Down Expand Up @@ -412,6 +412,13 @@ export interface RippleTarget {
rippleDisabled: boolean;
}

export declare type SanityChecks = boolean | {
doctype: boolean;
theme: boolean;
version: boolean;
hammer: boolean;
};

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<MatLine>, element: ElementRef<HTMLElement>): void;
Expand Down

0 comments on commit 47ade95

Please sign in to comment.