diff --git a/packages/platform-server/src/styles_host.ts b/packages/platform-server/src/styles_host.ts index 47aeba45d2..e8364cb183 100644 --- a/packages/platform-server/src/styles_host.ts +++ b/packages/platform-server/src/styles_host.ts @@ -13,6 +13,7 @@ import {ɵSharedStylesHost as SharedStylesHost, ɵTRANSITION_ID} from '@angular/ @Injectable() export class ServerStylesHost extends SharedStylesHost { private head: any = null; + private _styleNodes = new Set(); constructor( @Inject(DOCUMENT) private doc: any, @@ -29,9 +30,14 @@ export class ServerStylesHost extends SharedStylesHost { el.setAttribute('ng-transition', this.transitionId); } this.head.appendChild(el); + this._styleNodes.add(el); } onStylesAdded(additions: Set) { additions.forEach(style => this._addStyle(style)); } + + ngOnDestroy() { + this._styleNodes.forEach(styleNode => styleNode.remove()); + } } diff --git a/packages/platform-server/test/server_styles_host_spec.ts b/packages/platform-server/test/server_styles_host_spec.ts new file mode 100644 index 0000000000..5a0056fb13 --- /dev/null +++ b/packages/platform-server/test/server_styles_host_spec.ts @@ -0,0 +1,50 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {ɵgetDOM as getDOM} from '@angular/common'; +import {ServerStylesHost} from '@angular/platform-server/src/styles_host'; + + +(function() { +if (getDOM().supportsDOMEvents()) return; // NODE only + +describe('ServerStylesHost', () => { + let ssh: ServerStylesHost; + let documentHead: Element; + beforeEach(() => { + const doc = getDOM().createHtmlDocument(); + ssh = new ServerStylesHost(doc, ''); + documentHead = doc.head; + doc.querySelector('title')?.remove(); + }); + + it('should add existing styles', () => { + ssh.addStyles(['a {};']); + expect(documentHead.innerHTML).toEqual(''); + }); + + it('should add new styles to hosts', () => { + ssh.addStyles(['a {};']); + expect(documentHead.innerHTML).toEqual(''); + }); + + it('should add styles only once to hosts', () => { + ssh.addStyles(['a {};']); + ssh.addStyles(['a {};']); + expect(documentHead.innerHTML).toEqual(''); + }); + + it('should remove style nodes on destroy', () => { + ssh.addStyles(['a {};']); + expect(documentHead.innerHTML).toEqual(''); + + ssh.ngOnDestroy(); + expect(documentHead.innerHTML).toEqual(''); + }); +}); +})();