From c8192672678e4710f24956ed834ea6f77f96efe7 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Sun, 18 Feb 2018 01:54:58 +0100 Subject: [PATCH] fix(aria-describer): better handling of non-string values (#9959) Currently the `AriaDescriber` assumes that any values being described are going to be strings, however that may not be the case if a value is being passed it directly from the view. These changes add an extra check in order to avoid having to do null checks on consumption (see #9957). --- src/cdk/a11y/aria-describer/aria-describer.spec.ts | 9 +++++++++ src/cdk/a11y/aria-describer/aria-describer.ts | 10 ++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/cdk/a11y/aria-describer/aria-describer.spec.ts b/src/cdk/a11y/aria-describer/aria-describer.spec.ts index 7c117b5e43a..87d2cf8ab17 100644 --- a/src/cdk/a11y/aria-describer/aria-describer.spec.ts +++ b/src/cdk/a11y/aria-describer/aria-describer.spec.ts @@ -40,6 +40,15 @@ describe('AriaDescriber', () => { expect(getMessageElements()).toBe(null); }); + it('should not register non-string values', () => { + expect(() => ariaDescriber.describe(component.element1, null!)).not.toThrow(); + expect(getMessageElements()).toBe(null); + }); + + it('should not throw when trying to remove non-string value', () => { + expect(() => ariaDescriber.removeDescription(component.element1, null!)).not.toThrow(); + }); + it('should de-dupe a message registered multiple times', () => { ariaDescriber.describe(component.element1, 'My Message'); ariaDescriber.describe(component.element2, 'My Message'); diff --git a/src/cdk/a11y/aria-describer/aria-describer.ts b/src/cdk/a11y/aria-describer/aria-describer.ts index d0c99e4f9e5..b2fadcca910 100644 --- a/src/cdk/a11y/aria-describer/aria-describer.ts +++ b/src/cdk/a11y/aria-describer/aria-describer.ts @@ -60,7 +60,7 @@ export class AriaDescriber { * message element. */ describe(hostElement: Element, message: string) { - if (hostElement.nodeType !== this._document.ELEMENT_NODE || !message.trim()) { + if (!this._canBeDescribed(hostElement, message)) { return; } @@ -75,7 +75,7 @@ export class AriaDescriber { /** Removes the host element's aria-describedby reference to the message element. */ removeDescription(hostElement: Element, message: string) { - if (hostElement.nodeType !== this._document.ELEMENT_NODE || !message.trim()) { + if (!this._canBeDescribed(hostElement, message)) { return; } @@ -196,6 +196,12 @@ export class AriaDescriber { return !!messageId && referenceIds.indexOf(messageId) != -1; } + /** Determines whether a message can be described on a particular element. */ + private _canBeDescribed(element: Element, message: string): boolean { + return element.nodeType === this._document.ELEMENT_NODE && message != null && + !!`${message}`.trim(); + } + } /** @docs-private */