|
| 1 | +/** |
| 2 | + * @license |
| 3 | + * Copyright Google LLC All Rights Reserved. |
| 4 | + * |
| 5 | + * Use of this source code is governed by an MIT-style license that can be |
| 6 | + * found in the LICENSE file at https://angular.io/license |
| 7 | + */ |
| 8 | +import { |
| 9 | + APP_BOOTSTRAP_LISTENER, |
| 10 | + ApplicationRef, |
| 11 | + Inject, |
| 12 | + InjectionToken, |
| 13 | + Optional, |
| 14 | + PLATFORM_ID |
| 15 | +} from '@angular/core'; |
| 16 | +import {DOCUMENT, isPlatformBrowser, isPlatformServer} from '@angular/common'; |
| 17 | +import {take} from 'rxjs/operators/take'; |
| 18 | +import {filter} from 'rxjs/operators/filter'; |
| 19 | + |
| 20 | +import {EventReplayer} from './api/event.replayer'; |
| 21 | +import {PREBOOT_NONCE} from './common/tokens'; |
| 22 | +import {getInlinePrebootCode} from './api/inline.preboot.code'; |
| 23 | +import {PrebootOptions} from './common/preboot.interfaces'; |
| 24 | + |
| 25 | +const PREBOOT_SCRIPT_ID = 'preboot-inline-script'; |
| 26 | +export const PREBOOT_OPTIONS = new InjectionToken<PrebootOptions>('PrebootOptions'); |
| 27 | + |
| 28 | +export function PREBOOT_FACTORY(doc: Document, |
| 29 | + prebootOpts: PrebootOptions, |
| 30 | + nonce: string|null, |
| 31 | + platformId: Object, |
| 32 | + appRef: ApplicationRef, |
| 33 | + eventReplayer: EventReplayer) { |
| 34 | + return () => { |
| 35 | + if (isPlatformServer(platformId)) { |
| 36 | + const inlineCode = getInlinePrebootCode(prebootOpts); |
| 37 | + const script = doc.createElement('script'); |
| 38 | + if (nonce) { |
| 39 | + (<any>script)['nonce'] = nonce; |
| 40 | + } |
| 41 | + script.id = PREBOOT_SCRIPT_ID; |
| 42 | + script.textContent = inlineCode; |
| 43 | + const existingScripts = doc.querySelectorAll(`#${PREBOOT_SCRIPT_ID}`); |
| 44 | + |
| 45 | + // Check to see if a preboot script is already inlined before adding |
| 46 | + // it to the DOM. If it is, update the nonce to be current |
| 47 | + if (existingScripts.length === 0) { |
| 48 | + doc.head.appendChild(script); |
| 49 | + } else if (existingScripts.length > 0 && nonce) { |
| 50 | + (<any>existingScripts[0])['nonce'] = nonce; |
| 51 | + } |
| 52 | + } |
| 53 | + if (isPlatformBrowser(platformId)) { |
| 54 | + const replay = prebootOpts.replay != null ? prebootOpts.replay : true; |
| 55 | + if (replay) { |
| 56 | + appRef.isStable |
| 57 | + .pipe( |
| 58 | + filter(stable => stable), |
| 59 | + take(1) |
| 60 | + ).subscribe(() => { |
| 61 | + eventReplayer.replayAll(); |
| 62 | + }); |
| 63 | + } |
| 64 | + } |
| 65 | + }; |
| 66 | +} |
| 67 | + |
| 68 | +export const PREBOOT_PROVIDER = { |
| 69 | + provide: <InjectionToken<() => void>>APP_BOOTSTRAP_LISTENER, |
| 70 | + useFactory: PREBOOT_FACTORY, |
| 71 | + deps: [ |
| 72 | + DOCUMENT, |
| 73 | + PREBOOT_OPTIONS, |
| 74 | + [new Optional(), new Inject(PREBOOT_NONCE)], |
| 75 | + PLATFORM_ID, |
| 76 | + ApplicationRef, |
| 77 | + EventReplayer, |
| 78 | + ], |
| 79 | + multi: true |
| 80 | +}; |
0 commit comments