@@ -145,6 +145,10 @@ async function prerender (parentCompilation, request, options, inject, loader) {
145145 let result ;
146146 let dom , window , injectParent , injectNextSibling ;
147147
148+ // A promise-like that never resolves and does not retain references to callbacks.
149+ function BrokenPromise ( ) { }
150+ BrokenPromise . prototype . then = BrokenPromise . prototype . catch = BrokenPromise . prototype . finally = ( ) => new BrokenPromise ( ) ;
151+
148152 if ( compilation . assets [ compilation . options . output . filename ] ) {
149153 // Get the compiled main bundle
150154 const output = compilation . assets [ compilation . options . output . filename ] . source ( ) ;
@@ -181,6 +185,32 @@ async function prerender (parentCompilation, request, options, inject, loader) {
181185 window . requestAnimationFrame = ( ) => ++ counter ;
182186 window . cancelAnimationFrame = ( ) => { } ;
183187
188+ // Never prerender Custom Elements: by skipping registration, we get only the Light DOM which is desirable.
189+ window . customElements = {
190+ define ( ) { } ,
191+ get ( ) { } ,
192+ upgrade ( ) { } ,
193+ whenDefined : ( ) => new BrokenPromise ( )
194+ } ;
195+
196+ // Fake MessagePort
197+ window . MessagePort = function ( ) {
198+ ( this . port1 = new window . EventTarget ( ) ) . postMessage = ( ) => { } ;
199+ ( this . port2 = new window . EventTarget ( ) ) . postMessage = ( ) => { } ;
200+ } ;
201+
202+ // Never matches
203+ window . matchMedia = ( ) => ( { addListener ( ) { } } ) ;
204+
205+ // Never register ServiceWorkers
206+ if ( ! window . navigator ) window . navigator = { } ;
207+ window . navigator . serviceWorker = {
208+ register : ( ) => new BrokenPromise ( )
209+ } ;
210+
211+ // When DefinePlugin isn't sufficient
212+ window . PRERENDER = true ;
213+
184214 // Inject a require shim
185215 window . require = moduleId => {
186216 const asset = compilation . assets [ moduleId . replace ( / ^ \. ? \/ / g, '' ) ] ;
0 commit comments