diff --git a/packages/core/src/render3/i18n.ts b/packages/core/src/render3/i18n.ts index 6c0c5ec7b1..1377482c80 100644 --- a/packages/core/src/render3/i18n.ts +++ b/packages/core/src/render3/i18n.ts @@ -9,7 +9,7 @@ import '../util/ng_i18n_closure_mode'; import {DEFAULT_LOCALE_ID, getPluralCase} from '../i18n/localization'; import {getTemplateContent, SRCSET_ATTRS, URI_ATTRS, VALID_ATTRS, VALID_ELEMENTS} from '../sanitization/html_sanitizer'; -import {InertBodyHelper} from '../sanitization/inert_body'; +import {getInertBodyHelper} from '../sanitization/inert_body'; import {_sanitizeUrl, sanitizeSrcset} from '../sanitization/url_sanitizer'; import {addAllToArray} from '../util/array_utils'; import {assertDataInRange, assertDefined, assertEqual} from '../util/assert'; @@ -1233,7 +1233,7 @@ function icuStart( function parseIcuCase( unsafeHtml: string, parentIndex: number, nestedIcus: IcuExpression[], tIcus: TIcu[], expandoStartIndex: number): IcuCase { - const inertBodyHelper = new InertBodyHelper(getDocument()); + const inertBodyHelper = getInertBodyHelper(getDocument()); const inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml); if (!inertBodyElement) { throw new Error('Unable to generate inert body element'); diff --git a/packages/core/src/sanitization/html_sanitizer.ts b/packages/core/src/sanitization/html_sanitizer.ts index 4f79d98927..ab7bbbe836 100644 --- a/packages/core/src/sanitization/html_sanitizer.ts +++ b/packages/core/src/sanitization/html_sanitizer.ts @@ -7,7 +7,7 @@ */ import {isDevMode} from '../util/is_dev_mode'; -import {InertBodyHelper} from './inert_body'; +import {getInertBodyHelper, InertBodyHelper} from './inert_body'; import {_sanitizeUrl, sanitizeSrcset} from './url_sanitizer'; function tagSet(tags: string): {[k: string]: boolean} { @@ -245,7 +245,7 @@ let inertBodyHelper: InertBodyHelper; export function _sanitizeHtml(defaultDoc: any, unsafeHtmlInput: string): string { let inertBodyElement: HTMLElement|null = null; try { - inertBodyHelper = inertBodyHelper || new InertBodyHelper(defaultDoc); + inertBodyHelper = inertBodyHelper || getInertBodyHelper(defaultDoc); // Make sure unsafeHtml is actually a string (TypeScript types are not enforced at runtime). let unsafeHtml = unsafeHtmlInput ? String(unsafeHtmlInput) : ''; inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml); diff --git a/packages/core/src/sanitization/inert_body.ts b/packages/core/src/sanitization/inert_body.ts index e859f8af5a..9e3530be71 100644 --- a/packages/core/src/sanitization/inert_body.ts +++ b/packages/core/src/sanitization/inert_body.ts @@ -7,40 +7,29 @@ */ /** - * This helper class is used to get hold of an inert tree of DOM elements containing dirty HTML + * This helper is used to get hold of an inert tree of DOM elements containing dirty HTML * that needs sanitizing. * Depending upon browser support we use one of two strategies for doing this. - * Default: DomParser strategy + * Default: DOMParser strategy * Fallback: InertDocument strategy */ -export class InertBodyHelper { - private inertDocument: Document; - - constructor(private defaultDoc: Document) { - this.inertDocument = this.defaultDoc.implementation.createHTMLDocument('sanitization-inert'); - if (this.inertDocument.body == null) { - // usually there should be only one body element in the document, but IE doesn't have any, so - // we need to create one. - const inertHtml = this.inertDocument.createElement('html'); - this.inertDocument.appendChild(inertHtml); - const inertBodyElement = this.inertDocument.createElement('body'); - inertHtml.appendChild(inertBodyElement); - } - - this.getInertBodyElement = isDOMParserAvailable() ? this.getInertBodyElement_DOMParser : - this.getInertBodyElement_InertDocument; - } +export function getInertBodyHelper(defaultDoc: Document): InertBodyHelper { + return isDOMParserAvailable() ? new DOMParserHelper() : new InertDocumentHelper(defaultDoc); +} +export interface InertBodyHelper { /** * Get an inert DOM element containing DOM created from the dirty HTML string provided. - * The implementation of this is determined in the constructor, when the class is instantiated. */ getInertBodyElement: (html: string) => HTMLElement | null; +} - /** - * Use DOMParser to create and fill an inert body element in browsers that support it. - */ - private getInertBodyElement_DOMParser(html: string) { +/** + * Uses DOMParser to create and fill an inert body element. + * This is the default strategy used in browsers that support it. + */ +class DOMParserHelper implements InertBodyHelper { + getInertBodyElement(html: string): HTMLElement|null { // We add these extra elements to ensure that the rest of the content is parsed as expected // e.g. leading whitespace is maintained and tags like `` do not get hoisted to the // `` tag. @@ -54,13 +43,30 @@ export class InertBodyHelper { return null; } } +} - /** - * Use an HTML5 `template` element, if supported, or an inert body element created via - * `createHtmlDocument` to create and fill an inert DOM element. - * This is the fallback strategy if the browser does not support DOMParser. - */ - private getInertBodyElement_InertDocument(html: string) { +/** + * Use an HTML5 `template` element, if supported, or an inert body element created via + * `createHtmlDocument` to create and fill an inert DOM element. + * This is the fallback strategy if the browser does not support DOMParser. + */ +class InertDocumentHelper implements InertBodyHelper { + private inertDocument: Document; + + constructor(private defaultDoc: Document) { + this.inertDocument = this.defaultDoc.implementation.createHTMLDocument('sanitization-inert'); + + if (this.inertDocument.body == null) { + // usually there should be only one body element in the document, but IE doesn't have any, so + // we need to create one. + const inertHtml = this.inertDocument.createElement('html'); + this.inertDocument.appendChild(inertHtml); + const inertBodyElement = this.inertDocument.createElement('body'); + inertHtml.appendChild(inertBodyElement); + } + } + + getInertBodyElement(html: string): HTMLElement|null { // Prefer using